获取进程号

使用命令:jps

常用参数:

-m 输出传递给main方法的参数,如果是内嵌的JVM则输出为null。

-l 输出应用程序主类的完整包名,或者是应用程序JAR文件的完整路径。

-v 输出传给JVM的参数。

示例:

线程栈的获取

使用命令:jstack,通常使用管道将信息输出到文件,便于分析

常用参数:

-F 当jstack没有响应的时候强制打印栈信息。

-l 打印关于锁的附加信息,例如属于java.util.concurrent的ownable synchronizers列表。

-m 打印java和native c/c++框架的所有栈信息。

示例:

线程栈内容示例

2016-03-07 18:04:57
Full thread dump Java HotSpot(TM) Client VM (24.80-b11 mixed mode):"Attach Listener" daemon prio=10 tid=0xb7675000 nid=0x4a9 waiting on condition [0x00000000]java.lang.Thread.State: RUNNABLELocked ownable synchronizers:- None"Service Thread" daemon prio=10 tid=0xb766ec00 nid=0x44a runnable [0x00000000]java.lang.Thread.State: RUNNABLELocked ownable synchronizers:- None"C1 CompilerThread0" daemon prio=10 tid=0xb766d000 nid=0x449 waiting on condition [0x00000000]java.lang.Thread.State: RUNNABLELocked ownable synchronizers:- None"Signal Dispatcher" daemon prio=10 tid=0xb766b400 nid=0x448 runnable [0x00000000]java.lang.Thread.State: RUNNABLELocked ownable synchronizers:- None"Finalizer" daemon prio=10 tid=0xb765ac00 nid=0x447 in Object.wait() [0xa14ad000]java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on <0xa1a04750> (a java.lang.ref.ReferenceQueue$Lock)at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)- locked <0xa1a04750> (a java.lang.ref.ReferenceQueue$Lock)at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)Locked ownable synchronizers:- None"Reference Handler" daemon prio=10 tid=0xb7659400 nid=0x446 in Object.wait() [0xa14fe000]java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on <0xa1a043b8> (a java.lang.ref.Reference$Lock)at java.lang.Object.wait(Object.java:503)at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)- locked <0xa1a043b8> (a java.lang.ref.Reference$Lock)Locked ownable synchronizers:- None"main" prio=10 tid=0xb7606400 nid=0x444 waiting on condition [0xb77f2000]java.lang.Thread.State: TIMED_WAITING (sleeping)at java.lang.Thread.sleep(Native Method)at Test.main(Test.java:5)Locked ownable synchronizers:- None"VM Thread" prio=10 tid=0xb7656800 nid=0x445 runnable "VM Periodic Task Thread" prio=10 tid=0xb7671400 nid=0x44b waiting on condition JNI global references: 125

线程栈各部分介绍

  头部信息:

  示例:

  2016-03-07 18:04:57

  Full thread dump Java HotSpot(TM) Client VM (24.80-b11 mixed mode):

  内容:

  时间,jvm信息

  

  线程info信息块:

  示例:

  "Finalizer" daemon prio=10 tid=0xb765ac00 nid=0x447 in Object.wait() [0xa14ad000]

     java.lang.Thread.State: WAITING (on object monitor)

  at java.lang.Object.wait(Native Method)

  - waiting on <0xa1a04750> (a java.lang.ref.ReferenceQueue$Lock)

  at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)

  - locked <0xa1a04750> (a java.lang.ref.ReferenceQueue$Lock)

  at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)

  at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

  

     Locked ownable synchronizers:

  - None

  内容:

  线程名称:如Finalizer

  线程类型:如daemon

  优先级: 10,默认是5,如prio=10

  jvm线程id:tid=0xb765ac00,jvm内部线程的唯一标识(通过java.lang.Thread.getId()获取,通常用自增方式实现。)

  对应系统线程id(Native Thread ID):nid=0x447,和top命令查看的线程pid对应,不过一个是10进制,一个是16进制。(通过命令:top -H -p pid,可以查看该进程的所有线程信息)

  线程状态:in Object.wait().

  起始栈地址:[0xa14ad000]

  线程栈部分:包括线程当前状态和线程栈

线程栈分析工具

  IBM Thread and Monitor Dump Analyzer for Java

  官网主页:https://www.ibm.com/developerworks/community/groups/service/html/communityview?communityUuid=2245aa39-fa5c-4475-b891-14c205f7333c&lang=zh

  该工具是一个Jar包,可以使用命令启动

java -jar jca457.jar

  工作界面如下

JVM中的线程状态

  线程在JVM中的各个状态

  1.死锁,Deadlock(重点关注)

  2.执行中,Runnable(重点关注)

  3.等待资源,Waiting on condition(重点关注)

  4.等待监控器检查资源,Waiting on monitor(eg:如果使用System.out.println等需要分配计算机资源的时候线程会如此等待,主要还需看堆栈)

  5.暂停,Suspended

  6.对象等待中,Object.wait()

  7.阻塞,Blocked(重点关注)

  8.停止,Parked(主要是指线程空闲时候的状态。如在线程池中,当线程被调用后再次放入到池子中,则其状态变为了Parked)

JVM的Thin Lock, Fat Lock, Spin Lock与Tasuki Lock

  Java很多ThreadDump中,都可以看到Thin Lock, Fat Lock, Spin Lock,这些Lock都与Java语言、OS有密切的关系。

  回到一个简单的问题,在Java中,如何实现Synchronizd?

  最简单的一种做法是,利用OS的mutex机制,把Java的同步(基于Object),翻译成OS相关的monitor_enter和monitor_exit原语。

  回到Java锁本身,锁在不同的应用下有着不同的统计表现,而大部分的统计数据表明,其实线程抢锁,即锁竞争,都是短暂的,在大部分的情况下,几乎都不会发生锁竞争的现象。

  也就是说,Java锁,从安全性的角度来看,是有点累赘。

  因此,大量的专家都在锁上针对这样的统计特性对Java锁进行优化。

  其中一种优化方案是,我们对所有的锁都需要monitor_enter和monitor_exit吗?事实上不需要。

  如果我们把monitor_enter/monitor_exit看成是Fat Lock方式,则可以把Thin Lock看成是一种基于CAS(Compare and Swap)的简易实现。

  这两种锁,简单一点理解,就是:

  而基于CAS方式的实现,线程进入竞争状态的,获得锁的线程,会让其他线程处于自旋状态(也称之为Spin Mode,即自旋),这是一种while(Lock_release) doStuff()的Busy-Wait方式,是一种耗CPU的方式;而Fat Lock方式下,一个线程获得锁的时候,其他线程可以先sleep,等锁释放后,再唤醒(Notify)。

  CAS的优点是快,如果没有线程竞争的情况下,因为CAS只需要一个指令便获得锁,所以称之为Thin Lock,缺点也是很明显的,即如果频繁发生线程竞争,CAS是低效,主要表现为,排斥在锁之外的线程是Busy Wait状态;而monitor_enter/monitor_exit/monitor_notify方式,则是重量级的,在线程产生竞争的时候,Fat Lock在OS mutex方式下,可以实现no busy-wait。

  于是,JVM早期版本的做法是,如果T1, T2,T3,T4...产生线程竞争,则T1通过CAS获得锁(此时是Thin Lock方式),如果T1在CAS期间获得锁,则T2,T3进入SPIN状态直到T1释放锁;而第二个获得锁的线程,比如T2,会将锁升级(Inflation)为Fat Lock,于是,以后尝试获得锁的线程都使用Mutex方式获得锁。

  这种设计为锁提供了两条路径:Thin Lock路径和Fat Lock路径,大部分情况下,可能都是走Thin Lock路径,而可能少部分情况,是走Fat Lock路径,这种方式提供了锁升级,但是避免不了Busy Wait,而且Thin-Lock升级Fat-Lock之后,没有办法回退到Thin-Lock(性能比Fat-Lock更好)。

  Tasuki锁为这种方式做了2个优化:

  1) 避免CAS导致Busy wait

  2) Fat Lock可以deflate(与Inflate刚好相反)为Thin Lock(之前是Thin Lock变成Fat Lock之后便不能再回退)。

  经过这样的改造后,锁性能提高了10%以上。

  目前,Oracle的BEA JRockit与IBM的JVM都实现了Tasuki锁机制,唯一的不同是,在锁实现上都做了不同启发式的设计,即根据运行时采样的数据,动态调整一些权值数据,一边左右Lock Inflation/Lock Defaltion的过程(一颗树的两个分支),获取更好的锁性能。

参考文献

  Java线程池中线程的状态简介

  性能分析之-- JAVA Thread Dump 分析综述

  关于JVM的Thin Lock, Fat Lock, SPIN Lock与Tasuki Lock

转载于:https://blog.51cto.com/wangzhichao/1748503

Java线程栈的获取和分析相关推荐

  1. idea 线程内存_Java线程池系列之-Java线程池底层源码分析系列(一)

    课程简介: 课程目标:通过本课程学习,深入理解Java线程池,提升自身技术能力与价值. 适用人群:具有Java多线程基础的人群,希望深入理解线程池底层原理的人群. 课程概述:多线程的异步执行方式,虽然 ...

  2. idea 线程内存_Java线程池系列之-Java线程池底层源码分析系列(二)

    课程简介: 课程目标:通过本课程学习,深入理解Java线程池,提升自身技术能力与价值. 适用人群:具有Java多线程基础的人群,希望深入理解线程池底层原理的人群. 课程概述:多线程的异步执行方式,虽然 ...

  3. Java 线程池框架核心代码分析

    转载自 Java 线程池框架核心代码分析 前言 多线程编程中,为每个任务分配一个线程是不现实的,线程创建的开销和资源消耗都是很高的.线程池应运而生,成为我们管理线程的利器.Java 通过Executo ...

  4. java线程卡住排查_基于 Java 线程栈 排查问题

    除日志外,还有没有别的方式跟踪线上服务问题呢?或者,跟踪并排除日志里无法发现的问题? 方法当然是有的,就是通过现场快照定位并发现问题.我们所说的现场,主要指这两方面: Java 线程栈.线程栈是Jav ...

  5. Java线程池ThreadPoolExecutor使用和分析(三) - 终止线程池原理

    相关文章目录: Java线程池ThreadPoolExecutor使用和分析(一) Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理 Java线程池Thr ...

  6. Java线程池ThreadPoolExecutor使用和分析

    Java线程池ThreadPoolExecutor使用和分析(一) Java线程池ThreadPoolExecutor使用和分析(二) Java线程池ThreadPoolExecutor使用和分析(三 ...

  7. java 线程转储_获取Java线程转储的常用方法(推荐)

    1. 线程转储简介 线程转储(Thread Dump)就是JVM中所有线程状态信息的一次快照. 线程转储一般使用文本格式, 可以将其保存到文本文件中, 然后人工查看和分析, 或者使用工具/API自动分 ...

  8. Java 线程池框架核心代码分析--转

    原文地址:http://www.codeceo.com/article/java-thread-pool-kernal.html 前言 多线程编程中,为每个任务分配一个线程是不现实的,线程创建的开销和 ...

  9. Java线程池框架核心代码分析

    前言 多线程编程中,为每个任务分配一个线程是不现实的,线程创建的开销和资源消耗都是很高的.线程池应运而生,成为我们管理线程的利器.Java 通过Executor接口,提供了一种标准的方法将任务的提交过 ...

最新文章

  1. 复杂人机智能系统功能分配方法综述
  2. 響應式設計中百分比 % 的問題
  3. 重做53. Maximum Subarray
  4. oracle拆分字段为多行,一句话实现字段拆分成多行
  5. C语言中如何求一天是星期几,计算任何一天是星期几的C语言源代码.
  6. 福禄克网络电缆测试仪LinkIQ网络电缆测试仪的使用方法
  7. P3033 [USACO11NOV]牛的障碍Cow Steeplechase
  8. uva 1626——Brackets sequence
  9. 【收藏】机器学习数据集列表:你需要收藏!
  10. autojs toast 可以改变字体颜色吗_喃喃札记 | 你真的需要一部pad做笔记吗?
  11. 织梦网站建设广告网络公司网站模板 电脑+手机 整站源码
  12. 2006年~2011年记事简要
  13. Oracle Coherence中文教程三:配置
  14. 电脑显卡,台式电脑显卡怎么选择
  15. 手把手教你领取永久免费服务器
  16. 喜迎B+轮融资,ThingJS母公司优锘科技成为新基建的一匹黑马
  17. C++核心准则​Pro.bounds:边界安全群组
  18. Word 在试图打开文件时遇到错误 解决办法
  19. 八中计算机是学啥的,邹毅:我与CCF的不解之缘
  20. 今日头条-快速获取爆文素材的5大途经

热门文章

  1. python语言哪个人创造_Python语言是由哪个人创造的?
  2. python中修饰器_python 中的修饰器
  3. docker部署express项目
  4. JavaScript 代码片段
  5. android servlet乱码问题,初识 JSP---(Servlet映射 / ServletRequest / get与post区别 / 解决乱码)...
  6. hex转换成C语言源程序吗,第6节:把.c源代码编译成.hex机器码的操作流程
  7. 20211010 PHP笔记
  8. 20190911:(leetcode习题)计数质数
  9. php购物车paypal代码,PayPal购物车HTML代码
  10. zxr10交换机配置手册vlan_中兴ZXR10 G系列交换机SVLAN使用指导