JDK中自带的JVM分析工具

目录

  • 一、业务背景
  • 二、Jdk-Bin目录
  • 三、命令行工具
    • 1、jps命令
    • 2、jinfo命令
    • 3、jstat命令
    • 4、jstack命令
    • 5、jmap命令
  • 四、可视化工具
    • 1、jconsole
    • 2、visualvm
  • 五、参考源码
内存溢出,妥妥的名场面;
一、业务背景对于分布式架构中的文件服务来说 , 由于涉及大量的IO流操作,很容易引发JVM的相关异常,尤其是内存溢出的问题;
JDK中自带的JVM分析工具

文章插图
在最近的一次版本迭代中,真实的业务处理场景和上述几乎一致,由于在文件服务中添加批量处理的动作 , 直接唤醒了隐藏许久的BUG,就是最常见的内存溢出;
问题的起因:在word文档完成内容识别后,转换为pdf文件,然后进行页面分割转为一组图片,在这个复杂并且超长的流程中存在一个数组容器未销毁;
解决的方式:分析JVM的dump文件,定位OOM问题引发的根本原因,结合文件服务的异常日志分析,添加资源的释放动作,从而解决问题;
二、Jdk-Bin目录对于相当一部分新手来说,看到JVM的问题都是Bug不知所起一脸懵的,其实这种心态大可不必,从职场几年的开发经验上看,JVM的问题大致分为两种:
  • 开发轻松解决:可以升级内存资源或者调整分配,又或者对程序优化,完成相关资源的管理和释放,这是最常用的手段;
  • 轻松解决开发:由于经验不足,程序出现重大BUG导致JVM异常 , 进而引起系列的连锁反应 , 这种不会绝地反弹,只有一地鸡毛;
在解决常规的JVM异常时 , 通常依赖JDK中基础工具即可完成问题的定位,从而进行分析和解决,不过这些需要对基础工具熟练使用才行,而很多JDK自身的能力又是经常被忽略的;
在jdk的bin目录中,有很多自带工具可以用于对JVM的分析;
JDK中自带的JVM分析工具

文章插图
上述是基于jdk1.8的目录,里面有很多开发经常用到命令 , 下面围绕一个微服务的启动和运行 , 来看看基于JDK中自带JVM工具的用法;
三、命令行工具1、jps命令jps:虚拟机进程状态工具,该命令在Java环境部署和服务启动查看时经常用到,首先在本地启动一个facade门面微服务 , 然后在命令行中执行查询;
  • jps:命令默认输出的是进程ID和应用主类的名称;
  • -l:输出进程ID和应用主类的完整路径;
  • -v:输出向jvm传递的参数,此处展示为idea中显式配置的VM-options参数,其他内容自行查看即可;
  • -m:输出向main方法传递的参数,服务启动前可以在idea的Program-arguments配置;
$ jps1281 FacadeApp$ jps -l1281 com.explore.facade.FacadeApp$ jps -v1281 FacadeApp -Xms128m -Xmx256m -XX:MaxNewSize=256m -XX:MaxPermSize=256m$ jps -m1281 FacadeApp hello,main-method2、jinfo命令jinfo:在命令后面带pid进程号,可以输出指定进程的配置信息,在应用启动时通常不会指定过多的配置参数,就可以使用该命令查询很多参数的默认值;该命令还可以在运行时动态调整部分参数,只是很少被使用;
$ jinfo 1281# 只粘贴个别参数Java System Properties: # 系统参数java.runtime.version=1.8.0_144-b01file.encoding=UTF-8sun.java.command=com.explore.facade.FacadeApp hello,main-methodVM Flags:# 虚拟机参数-XX:InitialHeapSize=134217728 -XX:MaxHeapSize=268435456 -XX:MaxNewSize=267911168VM Arguments:# 运行时参数jvm_args: -Xms128m -Xmx256m -XX:MaxNewSize=256m -XX:MaxPermSize=256mjava_command: com.explore.facade.FacadeApp hello,main-method$ jinfo -sysprops 1281# 只输出【Java System Properties】参数$ jinfo -flags 1281# 只输出【VM Flags】参数3、jstat命令jstat:以指定的频率输出JVM的监控指标,下述命令输出内存占用和GC相关信息,每隔3秒输出一次 , 连续打印5次;由于这里只是启动一个简单的微服务,没有执行业务逻辑,所以各项指标比较平稳;
$ jstat -gcutil 1281 3000 5S0S1EOMCCSYGCYGCTFGCFGCTCGCCGCTGCT0.000.0057.9764.1692.8288.7530.02890.516--0.5440.000.0057.9764.1692.8288.7530.02890.516--0.544该命令是比较常用的,这里各项指标的统计逻辑,在tools.jar包中有jstat_options参考文档,相对路径sun/tools/jstat/resources/目录下;
option gcutil {column {header "^S0^" /* Survivor 0 Space - Percent Used */data (1-((sun.gc.generation.0.space.1.capacity - sun.gc.generation.0.space.1.used)/sun.gc.generation.0.space.1.capacity)) * 100}column {header "^S1^" /* Survivor 1 Space - Percent Used */data (1-((sun.gc.generation.0.space.2.capacity - sun.gc.generation.0.space.2.used)/sun.gc.generation.0.space.2.capacity)) * 100}......}

推荐阅读