深入理解Java虚拟机(4)-聊一聊JVM优化(后期持续更新)

213 阅读4分钟

JVM 性能优化工具记录

  • jps: 虚拟机进程状况工具 | 选项 | 作用 | | ---- | ---- | | -q | 只输出LVMID,省略主类的名称 | | -m | 输出虚拟机进程启动时传递给主类mian()函数的参数 | | -l | 输出主类的全名,如果进程执行的是Jar包,则输出JAR路径 | | -v | 输出虚拟机进程启动时的JVM参数 |

  • jstat | 选项 | 作用 | | ---- | ---- | |class | 用于查看类加载情况的统计,显示加载class的数量,及所占空间等信息。 |compiler | 查看HotSpot中即时编译器编译情况的统计 |gc | 查看JVM中堆的垃圾收集情况的统计,可以显示gc的信息,查看gc的次数,及时间。其中最后五项,分别是young gc的次数,young gc的时间,full gc的次数,full gc的时间,gc的总时间。 |gccapacity | 查看新生代、老生代及持久代的存储容量情况,可以显示,VM内存中三代(young,old,perm)对象的使用和占用大小 |gccause | 查看垃圾收集的统计情况(这个和-gcutil选项一样),如果有发生垃圾收集,它还会显示最后一次及当前正在发生垃圾收集的原因 |gcmetacapacity | 显示关于metaspace大小的统计信息。 |gcnew | 查看新生代垃圾收集的情况,new对象的信息 |gcnewcapacity | 用于查看新生代的存储容量情况,new对象的信息及其占用量 |gcold | 用于查看老生代及持久代发生GC的情况,old对象的信息 |gcoldcapacity | 用于查看老生代的容量,old对象的信息及其占用量 |gcpermcapacity | 用于查看持久代的容量,perm对象的信息及其占用量 |gcutil | 查看新生代、老生代及持代垃圾收集的情况 |printcompilation | 当前VM执行的信息

  • jinfo : 的作用是实时查看和调整虚拟机各项参数。 可以使用-flag[+|-]name或者-flag name=value在运行期修改一部分运行期可写的 虚拟机参数值 jinfo pid

查询CMSInitiatingOccupancyFraction参数值:

jinfo -flag CMSInitiatingOccupancyFraction 1444

  • jmap
选项作用
heap显示Java堆详细信息
histo显示堆中对象的统计信息
clstats打印类加载器信息
finalizerinfo显示在F-Queue队列等待Finalizer线程执行finalizer方法的对象
dump生成堆转储快照
F当-dump没有响应时,使用-dump或者-histo参数. 在这个模式下,live子参数无效.
help打印帮助信息
J指定传递给运行jmap的JVM的参数

jmap -dump:format=b,live,file=test.bin 8428

  • jhat jhat test.bin 访问地址: http://localhost:7000/

  • jstack | 选项 | 作用 | | ---- | ---- | | -F | 当正常输入的请求不被响应时,强制输出线程堆栈 | | -m | 如果调用本地方法的话可以显示C/C++的堆栈 | | -l | 除堆栈外,显示关于锁的附加信息 |

常用的界面工具JAVA VisualVM

遇到GC overhead limit exceeded触及JVM优化的问题

平时工作中涉及到JVM优化的问题少之又少,我理解的JVM优化的问题应该是:对于垃圾回收器的新生代老年代的在适用场景下的选型,Eden : From Survivor : To Survivor 的黄金比例调优, 新生代到老年代最佳年龄问题,暂时还没有遇到过这方面的场景,也不在这里硬拗了。次之,堆栈内存的设置问题。下面就简单记录一次简单的优化经历。预留文章篇幅,后期工作中有遇到持续更新。虽然没有很深刻的优化经历,但JVM的知识储备还是要有些研究的,对于JUC的学习和处理应急场景的解决思路还是很有帮助的。

项目开发框架SpringCloud架构,用户信息批量采集,对于大数据量的用户数据批量入库,界面没有办法做出及时响应,所以我们使用RabbitMq在用户上传文件时把文件信息作为生产者发布到消息队列,消费者使用POI用户模式进行异步消费处理。对于后端来说有校验文件条数,单次采集2w用户信息,但用户未按照模板上传,上传一份列特别长的文件,文件大小100M数据条数不到1w条的Excel。导致消息队列阻塞,同时看后台日志报错有一个GC overhead limit exceeded日志引起了我的注意。

解决办法:增加堆内存初始化大小和最大值 参数:

-Xmx Java Heap最大值,默认值为物理内存的1/4,最佳设值应该视物理内存大小及计算机内其他内存开销而定;

-Xms Java Heap初始值,Server端JVM最好将-Xms和-Xmx设为相同值,

同时删除错误消息,增加文件大小校验。

备用方式:使用POI+SAX模式 可以解析百万条数据内存也不会出现溢出的情况,当时没有采用这种方式进行提供,需要代码改动量较大。

熊猫笔记邮箱 : panda_nodes@163.com