「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战」
jps
JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程。
命令格式
jps [options] [hostid]
option参数
- -l : 输出主类全名或jar路径
- -q : 只输出LVMID
- -m : 输出JVM启动时传递给main()的参数
- -v : 输出JVM启动时显示指定的JVM参数
其中[option]、[hostid]参数也可以不写。
示例:
jstat
jstat 可以监测 Java 应用程序的实时运行情况,包括堆内存信息以及垃圾回收信息。
命令格式
jstat [option] LVMID [interval] [count]
option参数
- -class:显示 ClassLoad 的相关信息;
- -compiler:显示 JIT 编译的相关信息;
- -gc:显示和 gc 相关的堆信息;
- -gccapacity:显示各个代的容量以及使用情况;
- -gcmetacapacity:显示 Metaspace 的大小;
- -gcnew:显示新生代信息;
- -gcnewcapacity:显示新生代大小和使用情况;
- -gcold:显示老年代和永久代的信息;
- -gcoldcapacity :显示老年代的大小;
- -gcutil:显示垃圾收集信息;
- -gccause:显示垃圾回收的相关信息(通 -gcutil),同时显示最后一次或当前正在发生的垃圾回收的诱因;
- -printcompilation:输出 JIT 编译的方法信息。
常用介绍
使用jstat 查看堆内存的使用情况。我们可以用 jstat -gc pid 查看:
jstat -gc 62386
- S0C:年轻代中 To Survivor 的容量(单位 KB);
- S1C:年轻代中 From Survivor 的容量(单位 KB);
- S0U:年轻代中 To Survivor 目前已使用空间(单位 KB);
- S1U:年轻代中 From Survivor 目前已使用空间(单位 KB);
- EC:年轻代中 Eden 的容量(单位 KB);
- EU:年轻代中 Eden 目前已使用空间(单位 KB);
- OC:Old 代的容量(单位 KB);
- OU:Old 代目前已使用空间(单位 KB);
- MC:Metaspace 的容量(单位 KB);
- MU:Metaspace 目前已使用空间(单位 KB);
- YGC:从应用程序启动到采样时年轻代中 gc 次数;
- YGCT:从应用程序启动到采样时年轻代中 gc 所用时间 (s);
- FGC:从应用程序启动到采样时 old 代(全 gc)gc 次数;
- FGCT:从应用程序启动到采样时 old 代(全 gc)gc 所用时间 (s);
- GCT:从应用程序启动到采样时 gc 用的总时间 (s)。
每隔1000ms输出62386的gc情况,一共输出30次
jstat -gc 62386 1000 30
jmap
jmap主要用来查看java进程中的内存占用情况,常见用法:jmap -heap pid,jmap -histo pid ,jmap -dump:live,file={file} pid
命令格式
jmap [option] LVMID
option参数
- dump : 生成堆转储快照
- finalizerinfo : 显示在F-Queue队列等待Finalizer线程执行finalizer方法的对象
- heap : 显示Java堆详细信息
- histo : 显示堆中对象的统计信息
- permstat : to print permanent generation statistics
- F : 当-dump没有响应时,强制生成dump快照
jmap -heap pid
这个命令可以看到java进程中jvm 内存使用情况,实例如下:
如上图所以,可以看到jvm 内存的每个区的使用情况。但是这个值不怎么靠谱,所以这个值仅供参考
jmap -histo pid
这个命令是用来查看java线程中的对象个数及内存占用大小,示例如下:
从上图,我们可以看到每个类有多少的对象实例,一共占了多少字节。这个命令很方便的找到大对象。
jmap -dump:live,file={path} pid
我们可以通过 jmap 命令把堆内存的使用情况 dump 到文件中
我们可以将文件下载下来,使用 MAT 工具打开文件进行分析:
jstack
jstack用于生成java虚拟机当前时刻的线程快照
命令格式
jstack [option] LVMID
option参数
- -F : 当正常输出请求不被响应时,强制输出线程堆栈
- -l : 除堆栈外,显示关于锁的附加信息
- -m : 如果调用到本地方法的话,可以显示C/C++的堆栈
案例
如果你的程序出现了死锁,在stack.log中看到相应的提示,如:
Found one Java-level deadlock:
=============================
"t2":
which is held by "t1"
"t1":
which is held by "t2"
Java stack information for the threads listed above:
===================================================
"t2":
at testJstack$2.run(testJstack.java:29)
- waiting to lock <0x8c087670> (a java.lang.Object)
- locked <0x8c087678> (a java.lang.Object)
"t1":
at testJstack$1.run(testJstack.java:15)
- waiting to lock <0x8c087678> (a java.lang.Object)
- locked <0x8c087670> (a java.lang.Object)
Found 1 deadlock.
线程状态
NEW
至今尚未启动的线程的状态。当使用new一个新线程时,如new Thread(r),但还没有执行start(),线程还没有开始运行,这时线程的状态就是NEW。
RUNNABLE
可运行线程的线程状态。当start()方法被调用时,线程就进入RUNNABLE状态。此时的线程可能正在运行,也可能没有运行
BLOCKED
受阻塞并且正在等待监视器锁的某一线程的线程状态。下列情况会进入阻塞状态:
- 等待某个操作的返回,例如IO操作,该操作返回之前,线程不会继续下面的代码。
- 等待某个“锁”,在其他线程或程序释放这个“锁”之前,线程不会继续执行。
- 等待一定的触发条件。
- 线程执行了sleep方法。
- 线程被suspend()方法挂起。
一个被阻塞的线程在下列情况下会被重新激活:
- 执行了sleep()方法,睡眠时间已到。
- 等待的其他线程或程序持有的“锁”已被释放。
- 正在等待触发条件的线程,条件得到满足。
- 执行了suspend()方法,被调用了resume()方法。
- 等待的操作返回的线程,操作正确返回。
WAITING
某一等待线程的线程状态。线程因为调用了Object.wait()或Thread.join()而未运行,就会进入WAITING状态。
TIMED_WAITING
具有指定等待时间的某一等待线程的线程状态。线程因为调用了Thread.sleep(),或者加上超时值来调用Object.wait()或Thread.join()而未运行,则会进入TIMED_WAITING状态。
TERMINATED
已终止线程的线程状态。线程已运行完毕。
jstack thread栈信息分析
手动分析
手动分析需要对jstack的信息比较熟悉,重点关注blocked的线程,waiting for monitor entry,in Object.wait()以及RUNNABLE的线程,然后根据代码具体分析。
工具分析
线程dump的分析工具:
- IBM Thread and Monitor Dump Analyze for Java 一个小巧的Jar包,能方便的按状态,线程名称,线程停留的函数排序,快速浏览。
- 分享一个好用的Jstack分析工具——IBM Thread and Monitor Dump Analyzer for Java
- spotify.github.io/threaddump-… Spotify提供的Web版在线分析工具,可以将锁或条件相关联的线程聚合到一起。
本文已参与「新人创作礼」活动,一起开启掘金创作之路。