命令行:
- jps:虚拟机进程状况工具
- jstat:虚拟机统计信息监视工具
- jinfo:java配置信息工具
- jmap:java内存映射工具
- jhat:虚拟机堆转储快照分析工具
- jstack:java堆栈跟踪工具
- hsdis:jit生成代码反编汇
- 目录:D:\Program Files\jdk1.8.0_05\bin
- strace命令
可视化工具:
- jconsole:java监视与管理控制台
- visualvm:多合一故障处理工具
一、jps
https://blog.csdn.net/luxideyao/article/details/50506092
jps是jdk提供的一个查看当前java进程的小工具, 可以看做是JavaVirtual Machine Process Status Tool的缩写。非常简单实用。
命令格式:jps [options ] [ hostid ]
[options]选项 :
-q:仅输出VM标识符,不包括classname,jar name,arguments in main method
-m:输出main method的参数
-l:输出完全的包名,应用主类名,jar的完全路径名
-v:输出jvm参数
-V:输出通过flag文件传递到JVM中的参数(.hotspotrc文件或-XX:Flags=所指定的文件
-Joption:传递参数到vm,例如:-J-Xms512m
[hostid]:
[protocol:][[//]hostname][:port][/servername]
命令的输出格式 :
lvmid [ [ classname| JARfilename | "Unknown"] [ arg* ] [ jvmarg* ] ]
注意:如果需要查看其他机器上的jvm进程,需要在待查看机器上启动jstatd。
二、jstat
定义:
https://blog.csdn.net/zhaozheng7758/article/details/8623549
参数:
l class (类加载器)
l compiler (JIT)
l gc (GC堆状态)
l gccapacity (各区大小)
l gccause (最近一次GC统计和原因)
l gcnew (新区统计)
l gcnewcapacity (新区大小)
l gcold (老区统计)
l gcoldcapacity (老区大小)
l gcpermcapacity (永久区大小)
l gcutil (GC统计汇总)
l printcompilation (HotSpot编译统计)
jstat -gc 统计GC信息
一些术语的中文解释:
S0C:年轻代中第一个survivor(幸存区)的容量 (字节)
S1C:年轻代中第二个survivor(幸存区)的容量 (字节)
S0U:年轻代中第一个survivor(幸存区)目前已使用空间 (字节)
S1U:年轻代中第二个survivor(幸存区)目前已使用空间 (字节)
EC:年轻代中Eden(伊甸园)的容量 (字节)
EU:年轻代中Eden(伊甸园)目前已使用空间 (字节)
OC:Old代的容量 (字节)
OU:Old代目前已使用空间 (字节)
PC:Perm(持久代)的容量 (字节)
PU:Perm(持久代)目前已使用空间 (字节)
YGC:从应用程序启动到采样时年轻代中gc次数
YGCT:从应用程序启动到采样时年轻代中gc所用时间(s)
FGC:从应用程序启动到采样时old代(全gc)gc次数
FGCT:从应用程序启动到采样时old代(全gc)gc所用时间(s)
GCT:从应用程序启动到采样时gc用的总时间(s)
jstat -gccapacity
可以显示,VM内存中三代(young,old,perm)对象的使用和占用大小
指定java程序运行内存大小
-Xms -Xmx -Xmn 等,然后观察jstat的结果
增加gc参数,java程序自动输出gc日志
vm option: -Xms20M -Xmx20M -Xmn10M
-verbose:gc -XX:+PrintGCDetails -XX:SurvivorRatio=8
说明:
-XX:+PrintGCDetails参数用于告诉虚拟机在发生垃圾收集行为时打印内存回收日志,并且在进程退出的时候输出当前内存的各区域分配情况。
输出日志:
[GC (System.gc()) [PSYoungGen: 7497K->64K(236032K)] 35038K->27604K(1022464K), 0.0022938 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (System.gc()) [PSYoungGen: 64K->0K(236032K)] [ParOldGen: 27540K->27540K(786432K)] 27604K->27540K(1022464K), [Metaspace: 40881K->40881K(1087488K)], 0.0429459 secs] [Times: user=0.09 sys=0.00, real=0.04 secs]
https://www.cnblogs.com/xuezhiyizu1120/p/6237510.html
使用jinfo动态修改程序gc参数,协助调试
jinfo -flag +PrintGCDetails
jinfo -flag +PrintGC
jinfo -flag +PrintGCTimeStamps 输出GC的时间戳(以基准时间的形式)
jinfo -flag +PrintGCDateStamps 输出GC的时间戳(以日期的形式,如 2013-05-04T21:53:59.234+0800)
jinfo -flag +PrintHeapAtGC 在进行GC的前后打印出堆的信息
jinfo -flag -Xloggc:../logs/gc.log 日志文件的输出路径
-verbose:gc -Xloggc:$CATALINA_HOME/logs/gc.log
-Xms100m -Xmx100m -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -verbose:gc -Xloggc:/usr/local/e6atlasbus/canbus/canbus-server/gc_logs/gc.log
更改gc参数
https://www.cnblogs.com/gouge/p/9112782.html
三、jinfo
jinfo 是jdk自带的一个工具,它可以用来查看正在运行的java应用程序的扩展参数(JVM中-X标示的参数);甚至支持在运行时修改部分参数。
jinfo 223536 > tmp/jinfo.txt 获取jvm进程的所有信息
关键字:VM Flags
动态修改命令:
通过以下的命令你便能看到JVM中哪些flag可以被jinfo动态修改:
java -XX:+PrintFlagsFinal -version | grep manageable
https://blog.csdn.net/liuxiao723846/article/details/72701414
四、jmap
jmap命令(Java Memory Map)是其中之一。主要用于打印指定Java进程(或核心文件、远程调试服务器)的共享对象内存映射或堆内存细节。
jmap命令可以获得运行中的jvm的堆的快照,从而可以离线分析堆,以检查内存泄漏,检查一些严重影响性能的大对象的创建,检查系统中什么对象最多,各种对象所占内存的大小等等。可以使用jmap生成Heap Dump。
java memory = direct memory(直接内存) + jvm memory(MaxPermSize +Xmx)
JVM直接内存:
直接内存区并不是 JVM 管理的内存区域的一部分,而是其之外的。该区域也会在 Java 开发中使用到,并且存在导致内存溢出的隐患。
https://blog.csdn.net/leaf_0303/article/details/78961936
https://www.cnblogs.com/wangjzh/p/5258254.html
常用命令:
jmap -heap
jmap -histo:live
jmap -dump:live,format=b,file=/f/dump.dat
jhat /f/dump.dat 分析dump文件
https://www.cnblogs.com/kongzhongqijing/articles/3621163.html
dump文件分析
jvisualvm
OQL 分析dump文件 https://www.aliyun.com/jiaocheng/299417.html
select x from com.e6yun.preprocessor.processor.jcmd.JCmdObject x
dump文件中的线程分析->jstack命令
总结
1.如果程序内存不足或者频繁GC,很有可能存在内存泄露情况,这时候就要借助Java堆Dump查看对象的情况。
2.要制作堆Dump可以直接使用jvm自带的jmap命令
3.可以先使用jmap -heap命令查看堆的使用情况,看一下各个堆空间的占用情况。
4.使用jmap -histo:[live]查看堆内存中的对象的情况。如果有大量对象在持续被引用,并没有被释放掉,那就产生了内存泄露,就要结合代码,把不用的对象释放掉。
5.也可以使用 jmap -dump:format=b,file=
6.在内存出现泄露、溢出或者其它前提条件下,建议多dump几次内存,把内存文件进行编号归档,便于后续内存整理分析。
7.在用cms gc的情况下,执行jmap -heap有些时候会导致进程变T,因此强烈建议别执行这个命令,如果想获取内存目前每个区域的使用状况,可通过jstat -gc或jstat -gccapacity来拿到。
五、jhat
jhat也是jdk内置的工具之一。主要是用来分析java堆的命令,可以将堆中的对象以html的形式显示出来,包括对象的数量,大小等等,并支持对象查询语言。
https://www.cnblogs.com/baihuitestsoftware/articles/6406271.html
jhat /f/dump.dat 分析dump文件
使用jvisualvm可视化工具替代
六、jstack
jstack命令主要用生成java虚拟机当前时刻的线程快照,来查看Java线程的调用堆栈的,可以用来分析线程问题(如死锁)。
http://www.cnblogs.com/kongzhongqijing/articles/3630264.html
命令格式:
jstack [ option ] pid
jstack [ option ] executable core
jstack [ option ] [server-id@]remote-hostname-or-IP
常用参数说明
1)options:
executable Java executable from which the core dump was produced.(可能是产生core dump的java可执行程序)
core 将被打印信息的core dump文件
remote-hostname-or-IP 远程debug服务的主机名或ip
server-id 唯一id,假如一台主机上多个远程debug服务
2)基本参数:
-F 当’jstack [-l] pid’没有相应的时候强制打印栈信息,如果直接jstack无响应时,用于强制jstack),一般情况不需要使用
-l 长列表. 打印关于锁的附加信息,例如属于java.util.concurrent的ownable synchronizers列表,会使得JVM停顿得长久得多(可能会差很多倍,比如普通的jstack可能几毫秒和一次GC没区别,加了-l 就是近一秒的时间),-l 建议不要用。一般情况不需要使用
-m 打印java和native c/c++框架的所有栈信息.可以打印JVM的堆栈,显示上Native的栈帧,一般应用排查不需要使用
-h | -help 打印帮助信息
pid 需要被打印配置信息的java进程id,可以用jps查询.
线程状态:
NEW
未启动的。不会出现在Dump中。
RUNNABLE
在虚拟机内执行的。运行中状态,可能里面还能看到locked字样,表明它获得了某把锁。
BLOCKED
受阻塞并等待监视器锁。被某个锁(synchronizers)給block住了。
WATING
无限期等待另一个线程执行特定操作。等待某个condition或monitor发生,一般停留在park(), wait(), sleep(),join() 等语句里。
TIMED_WATING
有时限的等待另一个线程的特定操作。和WAITING的区别是wait() 等语句加上了时间限制 wait(timeout)。
TERMINATED
已退出的。
Monitor
在多线程的 JAVA程序中,实现线程之间的同步,就要说说 Monitor。 Monitor是 Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁。每一个对象都有,也仅有一个 monitor。这就是wait,notify等方法在Object类的原因。
调用修饰
表示线程在方法调用时,额外的重要的操作。线程Dump分析的重要信息。修饰上方的方法调用。
locked <地址> 目标:使用synchronized申请对象锁成功,监视器的拥有者。
waiting to lock <地址> 目标:使用synchronized申请对象锁未成功,在迚入区等待。
waiting on <地址> 目标:使用synchronized申请对象锁成功后,释放锁幵在等待区等待。
parking to wait for <地址> 目标
线程动作,线程状态产生的原因
runnable:状态一般为RUNNABLE。
in Object.wait():等待区等待,状态为WAITING或TIMED_WAITING。
waiting for monitor entry:进入区等待,状态为BLOCKED。
waiting on condition:等待区等待、被park。
sleeping:休眠的线程,调用了Thread.sleep()。
jstack 解决问题实例
http://www.iteye.com/topic/1114219
http://note.youdao.com/noteshare?id=4e05478b110f1d22fbaeb3a740671a00
分析问题入手点总结:
wait on monitor entry: 被阻塞的,肯定有问题
runnable : 注意IO线程
in Object.wait(): 注意非线程池等待
分析经验:
对于jstack做的ThreadDump的栈,可以反映如下信息:
- 如果某个相同的call stack经常出现, 我们有80%的以上的理由确定这个代码存在性能问题(读网络的部分除外);
- 如果相同的call stack出现在同一个线程上(tid)上, 我们很很大理由相信, 这段代码可能存在较多的循环或者死循环;
- 如果某call stack经常出现, 并且里面带有lock,请检查一下这个lock的产生的原因, 可能是全局lock造成了性能问题;
- 在一个不大压力的群集里(w<2), 我们是很少拿到带有业务代码的stack的, 并且一般在一个完整stack中, 最多只有1-2业务代码的stack,
- 如果经常出现, 一定要检查代码, 是否出现性能问题。
- 如果你怀疑有dead lock问题, 那么请把所有的lock id找出来,看看是不是出现重复的lock id。
频繁GC问题或内存溢出问题
一、使用jps查看线程ID
二、使用jstat -gc 3331 250 20 查看gc情况,一般比较关注PERM区的情况,查看GC的增长情况。
三、使用jstat -gccause:额外输出上次GC原因
四、使用jmap -dump:format=b,file=heapDump 3331生成堆转储文件
五、使用jhat或者可视化工具(Eclipse Memory Analyzer 、IBM HeapAnalyzer)分析堆情况。
六、结合代码解决内存溢出或泄露问题。
死锁问题
一、使用jps查看线程ID
二、使用jstack 3331:查看线程情况
六、hsdis
略