学软件技术,读第一手资料,去官方网站:Java SE Specifications
若想看垃圾收集的简易版本的,参见:Java垃圾收集基础
给一个系统定位的问题,知识、经验是关键基础,数据是依据,工具是运用知识处理数据的手段。这里说的数据包括:运行日志、异常堆栈、GC日志、线程快照(threaddump/javacore文件)、堆转储快照(heapdump/hprof文件)等。合理运用虚拟机监控和分析工具可以加快我们分析数据,定位解决问题。
1、jps(功能单一,使用频率最高)
jps(JVM Process Status Tool),查正在运行的虚拟机进程,并显示虚拟机主类(Main Class,main()函数所在的类)名称以及这些进程的本地虚拟机唯一ID(Local Virtual Machine Identifier,LVMID)。对于其他的JDK工具大多需要输入它查询到的LVMID来确定要监控的是哪一个虚拟机进程。
jps命令格式:
jps [options] [hostid]
2、jstat(在没有GUI图形界面时,它是运行期定位虚拟机性能问题的首选工具)
jstat(JVM Statistics Monitoring Tool)是查询虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据,在没有GUI图形界面时,它是运行期定位虚拟机性能问题的首选工具。
命令格式:
jstat [option LVMID [interval[s|ms] [count] ] ]
参数interval和count代表查询间隔和次数,如果省略这两个参数,说明只查询一次。假设需要每2000毫秒查询一次进程1080垃圾收集状况,一共查询10次,那命令就是:
jstat -gc 1080 2000 10
S0C:第一个幸存区的大小
S1C:第二个幸存区的大小
S0U:第一个幸存区的使用大小
S1U:第二个幸存区的使用大小
EC:伊甸园区的大小
EU:伊甸园区的使用大小
OC:老年代大小
OU:老年代使用大小
MC:方法区大小
MU:方法区使用大小
CCSC:压缩类空间大小
CCSU:压缩类空间使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
选项option代表着用户希望查询的虚拟机信息,主要分为3类:类装载、垃圾收集、运行期编译状况,具体选项和作用如下:
3、jinfo(实时地查看和调整虚拟机各项参数)
jinfo(Configuration Info for Java)的作用是实时地查看和调整虚拟机各项参数。
命令格式:
jinfo [option] <pid>
options参数解释:
- -flag <name> 打印指定名称的参数
- -flag [+|-]<name> 打开或关闭参数
- -flag <name>=<value> 设置参数
- -flags 打印所有参数
- -sysprops 打印系统配置
- <no option> 打印上面两个选项
最常用示例:
其中11666为pid
查看JVM参数和系统配置
1 2 3 |
|
查看打印GC日志参数
1 2 |
|
打开GC日志参数
1 2 |
|
关闭GC日志参数
1 2 |
|
还可以使用下面的命令查看那些参数可以使用jinfo命令来管理:
1 |
|
常用JVM参数:
-Xms:初始堆大小,默认为物理内存的1/64(<1GB);默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制
-Xmx:最大堆大小,默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制
-Xmn:新生代的内存空间大小,注意:此处的大小是(eden+ 2 survivor space)。与jmap -heap中显示的New gen是不同的。整个堆大小=新生代大小 + 老生代大小 + 永久代大小。
在保证堆大小不变的情况下,增大新生代后,将会减小老生代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
-XX:SurvivorRatio:新生代中Eden区域与Survivor区域的容量比值,默认值为8。两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10。
-Xss:每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。应根据应用的线程所需内存大小进行适当调整。在相同物理内存下,
减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。一般小的应用, 如果栈不是很深, 应该是128k够用的,
大的应用建议使用256k。这个选项对性能影响比较大,需要严格的测试。和threadstacksize选项解释很类似,官方文档似乎没有解释,
在论坛中有这样一句话:"-Xss
is
translated
in
a VM flag named ThreadStackSize”一般设置这个值就可以了。
-XX:PermSize:设置永久代(perm gen)初始值。默认值为物理内存的1/64。
-XX:MaxPermSize:设置持久代最大值。物理内存的1/4。
4、jmap(堆转储快照,dump、Java堆、永久代信息等)
jmap(Memory Map for Java)命令用于生成堆转储快照(一般称为dump文件或者heapdump)。
除了可以获取dump文件,它还可以查询finalize执行队列、Java堆和永久代的信息,如空间利用率、当前使用的哪种收集器等。
命令格式:
jmap [option] <pid> (连接正在执行的进程)
jmap [option] <executable <core> (连接一个core文件)
jmap [option] [server_id@]<remote server IP or hostname> (链接远程服务器)
option参数解释:
- <none> to print same info as Solaris pmap
- -heap 打印java heap摘要
- -histo[:live] 打印堆中的java对象统计信息
- -clstats 打印类加载器统计信息
- -finalizerinfo 打印在f-queue中等待执行finalizer方法的对象
- -dump:<dump-options> 生成java堆的dump文件
dump-options:
live 只转储存活的对象,如果没有指定则转储所有对象
format=b 二进制格式
file=<file> 转储文件到 <file>
- -F 强制选项
常用示例:
1 |
|
输出:
1 2 |
|
这个命令是要把java堆中的存活对象信息转储到dump.hprof文件
1 |
|
输出:
1 2 3 4 5 |
|
输出结果的含义为当前没有在等待执行finalizer方法的对象
1 |
|
输出堆的详细信息
输出:
Attaching to process ID 11666, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.25-b02 using thread-local object allocation. Parallel GC with 4 thread(s) Heap Configuration: //堆内存初始化配置 MinHeapFreeRatio = 0 //对应jvm启动参数-XX:MinHeapFreeRatio设置JVM堆最小空闲比率(default 40) MaxHeapFreeRatio = 100 //对应jvm启动参数 -XX:MaxHeapFreeRatio设置JVM堆最大空闲比率(default 70) MaxHeapSize = 1073741824 (1024.0MB) //对应jvm启动参数-XX:MaxHeapSize=设置JVM堆的最大大小 NewSize = 22020096 (21.0MB) //对应jvm启动参数-XX:NewSize=设置JVM堆的新生代的默认大小 MaxNewSize = 357564416 (341.0MB) //对应jvm启动参数-XX:MaxNewSize=设置JVM堆的新生代的最大大小 OldSize = 45088768 (43.0MB) //对应jvm启动参数-XX:OldSize=<value>:设置JVM堆的老年代的大小 NewRatio = 2 //对应jvm启动参数-XX:NewRatio=:新生代和老生代的大小比率 SurvivorRatio = 8 //对应jvm启动参数-XX:SurvivorRatio=设置新生代中Eden区与Survivor区的大小比值 MetaspaceSize = 21807104 (20.796875MB) // 元数据区大小 CompressedClassSpaceSize = 1073741824 (1024.0MB) //类压缩空间大小 MaxMetaspaceSize = 17592186044415 MB //元数据区最大大小 G1HeapRegionSize = 0 (0.0MB) //G1垃圾收集器每个Region大小 Heap Usage: //堆内存使用情况 PS Young Generation Eden Space: //Eden区内存分布 capacity = 17825792 (17.0MB) //Eden区总容量 used = 12704088 (12.115562438964844MB) //Eden区已使用 free = 5121704 (4.884437561035156MB) //Eden区剩余容量 71.26801434685203% used //Eden区使用比率 From Space: //其中一个Survivor区的内存分布 capacity = 2097152 (2.0MB) used = 1703936 (1.625MB) free = 393216 (0.375MB) 81.25% used To Space: //另一个Survivor区的内存分布 capacity = 2097152 (2.0MB) used = 0 (0.0MB) free = 2097152 (2.0MB) 0.0% used PS Old Generation capacity = 52428800 (50.0MB) //老年代容量 used = 28325712 (27.013504028320312MB) //老年代已使用 free = 24103088 (22.986495971679688MB) //老年代空闲 54.027008056640625% used //老年代使用比率 15884 interned Strings occupying 2075304 bytes.
5、jhat(看dump文件的工具)
jhat(JVM Heap Analysis Tool)命令与jmap搭配使用,来分析jmap生成的堆转储快照(dump文件)。一般很少用这个工具 , 因为太简陋。
6、jstack(Java堆栈跟踪工具)
jstack(Stack Trace for Java)命令用于生成虚拟机当前时刻的线程快照(一般称为threaddump或者javacore文件)。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待都是导致线程长时间停顿的常见原因。线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做了什么事情,或者等待着什么资源。
jstack 命令格式:
jstack [option] vmid