jvm调优和jvm工具总结
jvm 调优和工具总结
jvm 工具
jps
查看java运行的进程信息。拿到进程id 后,会根据指定的进程id查看内部详细的内存情况。

jmap
jmap 工具可用来查询内存占用和实例生成统计信息。
打印进程当前的所有的实例统计信息
jmap -histo 19616

查看整个堆的统计信息
jmap -heap 19616

导出整个堆的信息
jmap -dump:format=b,file=nacos.hprof 19616

线上导出的文件,通过本地机器的jvm工具 jvisualvm ,可以导入查看
操作步骤为 左上角 –> 装入 –> 选择文件类型 –> 堆dump –> 打开即可。
内存溢出问题定位
- 配置参数 -XX:+HeapDumpOnOutOfMemoryError 和 -xx:HeapDumpPath=./j.dump 主要需要再-jar 之前
- 获取到内存溢出的文件后,可以将文件导入到 jvisvium 中,装入–> 选择类型 –> 堆dump –> 选择文件;
- 查看类信息,查看哪些类的数量最多,大致可分析出是因为什么对象导致的内存溢出。
jstack
jstack 用来查看java线程的调用堆栈,一般用来分析线程问题。
jstack pid

可以看到所有线程的状态,并且如果出现死锁问题,也会提示。
jinfo
查看目前生效的jvm参数
有时候明明设置了jvm参数,但是并没有按照期望的运行,那么可以查看是否是因为未生效的原因;
查看所有参数: jinfo -flags pid
动态添加或删除参数: jinfo -flag [param] id
jstat
用来查询内存的使用情况。
- jstat -gc pid 打印一次gc使用情况

jstat -gc pid 1000 10 间隔1秒,执行10次统计情况,可以看出内存的动态变化情况
jstat -gccapacity pid 堆内存统计
jstat -gcnew pid 新生代垃圾回收统计
jstat -gcnewcapacity pid 新生代内存统计
jstat -gcold 16000 老年代垃圾回收统计
jstat -gcoldcapacity 16000 老年代内存统计
jstat -gcmetacapacity pid 元空间空间统计
jstat -gcutil pid 整体使用比例统计
jconsole
包含了 概述、内存、线程、类、VM概要、MBean等内容的可视化jvm功能
执行命令 jconsole 打开
jvisualvm
JVM可视化性能监测工具。通过执行 jvisualvm 打开。
也用于分析线上的内存jump文件
常见调优分析
cpu过高如何定位
- 找到消耗最高cpu的进程id
1 | top |
- 查看此进程id内哪个线程是销毁cpu最高的线程
1 | top -H -p pid //pid 是上一步拿到的进程id |
- 将获取到的线程id 转成16进程,因为jstack中的线程id是16进制显示的
1 | echo "obase=16;xxxx" | bc //xxxx 是要转换的10进程 id |
- jstack pid | grep tid(16进制的) -A 30 //查询此检查后30行的数据
频繁fullgc 怎么定位
对于jvm中绝大部分的对象应该是朝生夕死的,应该是年轻代经过younggc被回收掉;
发生fullgc 是老年代满了后才会发生fullgc,而从年轻代到老年代,几种常见的原因
– 长期存活的对象,达到分代年龄
– 大对象,对象的大小超过设置的值
– 动态年龄判断机制,当一部分survior 中的对象超过空间的一半,那么最大的年龄的对象进入老年代
– 老年代空间担保机制 当发生minorgc的时候,如果老年代剩余空间小于年轻代所有的对象的空间的合;会判断是否开启了一个配置,如果配置未开启
或 可用空间小于之前的minoorgc 进入老年代的平均大小,就fullgc 否则就minorgc;通过工具 jstat -gc pid 1000 10 查看垃圾产生的速率,观察fullgc发生的平均时间;
可能会因为动态年龄判断机制导致的fullgc,那么可以尝试增加年轻代的大小;查看是否还有fullgc
还可能因为老年代空间担保机制导致的,可能出现的现象是fullgc 比minorgc 还要多;可以通过jmap -histo 命令查看是否有频繁的大对象产生;
-XX:-+DisableExplicitGC 禁用System.gc()
元空间扩容也会发生fullgc ,但是不会一直fullgc;一般是在启动的时候
jvm 如何调优
合理调整堆空间的大小,元空间大小
选择合适的垃圾收集器
垃圾收集器如何选择
- 优先调整堆内存,让服务器自己选择垃圾收集器
- 如果内存小于100M,使用串行垃圾收集器
- 如果是单核,并且没有停顿时间要求,串行或jvm自己选择
- 如果停顿时间超过1秒,选择并行或jvm自己选
- 如果响应时间最重要,并且不能超过1秒,使用并发收集器
- 4G以下用parallel,4-8G可以用ParNew+CMS,8G以上可以用G1,几百G以上用ZGC
打印gc日志,监控fullgc
尽量的减少fullgc


