Java 虚拟机入门教程之五 JVM 性能优化

大纲

前言

JVM 调优,调的是稳定,并不能让性能得到大幅提升。服务稳定的重要性就不用多说了,保证服务的稳定,GC 永远会是 JAVA 程序员需要考虑的不稳定因素之一。复杂和高并发下的服务,必须保证每次 GC 不会出现性能下降,各种性能指标不会出现波动,GC 回收规律而且干净,找到合适的 JVM 设置。比如,FULL GC 最会影响性能,根据代码问题,避免 FULL GC 频率。可以适当调大年轻代的容量,让大对象可以在年轻代触发 YONG GC,调整大对象在年轻代的回收频次,尽可能保证大对象在年轻代回收,减小老年代缩短回收时间。

性能优化工具的介绍

工具说明
jstack 查看 JVM 线程运行状态,是否有死锁现象等信息
jinfo 可以输出并修改运行时的 Java 进程的 opts
jps 与 Unix 上的 ps 命令类似,用来显示本地的 Java 进程,可以查看本地运行着几个 Java 程序,并显示它们的进程号
jstat 一个极强的监视 VM 内存工具。可以用来监视 VM 内存内的各种堆和非堆的大小及其内存使用量
jmap 打印出某个 Java 进程(使用 pid)内存内的所有 对象 的情况(如:产生哪些对象及其数量)

性能优化工具的使用

在使用下述工具前,建议先用 jps 命令获取当前的每个 JVM 进程号,然后再选择要查看的 JVM 进程。

jstat 使用

jstat 是 JDK 自带的工具,特别强大,参数有众多的可选项,可详细地查看堆内各个部分的使用量,以及类加载的数量。使用时,需加上应用的进程 id 和所选参数。

命令说明
jstat -class pid 显示加载 Class 的数量,及所占空间等信息
jstat -compiler pid 显示 VM 实时编译的数量等信息
jstat -gc pid 显示 GC 的信息,查看 GC 的次数与时间
jstat -gccapacity pid 堆内存统计,包括堆内存的使用和占用大小
jstat -gcnew pid 新生代垃圾回收统计
jstat -gcnewcapacity pid 新生代内存统计
jstat -gcold pid 老年代垃圾回收统计
jstat -gcutil pid 堆内存(包括新生代、老年代)的垃圾回收统计

除了以上 pid 参数外,还可以同时加上两个数字,示例如下:

  • jstat -gcutil pid 1000 100: 每 1000 毫秒统计一次 GC 情况,一共统计 100 次
  • jstat -printcompilation pid 250 6: 表示每 250 毫秒打印一次,一共打印 6 次,还可以加上 -h3 参数使每三行显示一次标题

jinfo 使用

jinfo 是 JDK 自带的工具,可以用来查看正在运行的 Java 应用程序的扩展参数,包括 Java System 属性和 JVM 命令行参数;也可以动态地修改正在运行的 JVM 一些参数。当系统崩溃时,jinfo 可以从 core 文件里面知道崩溃的 Java 应用程序的配置信息。

命令说明
jinfo pid 输出当前 JVM 进程的全部参数和系统属性
jinfo -flag name pid 查看指定的 JVM 参数的值,打印结果: - 无此参数,`+ 有此参数
jinfo -flag [+/-]name pid 开启或者关闭对应名称的参数(无需重启虚拟机)
jinfo -flag name=value pid 修改指定参数的值
jinfo -flags pid 输出全部的参数
jinfo -sysprops pid 输出当前 JVM 进行的全部的系统属性

jmap 使用

jmap 是 JDK 自带的工具,可以生成堆内存的 Dump 文件,也可以查看堆内对象分析内存信息等,如果不使用这个命令,还可以使用 -XX:+HeapDumpOnOutOfMemoryError 参数来让虚拟机在出现 OOM 的时候自动生成 Dump 文件。

命令说明
jmap -dump:live,format=b,file=product.dump pidDump 堆内存到指定的文件,format 指定输出格式,live 指明是活着的对象,file 指定文件名。Eclipse 可以直接打开这个文件
jmap -heap pid 打印堆内存的概要信息,包括 GC 使用的算法、堆内存的配置和使用情况,可以用此来判断目前内存的使用情况以及垃圾回收情况
jmap -finalizerinfo pid 打印等待回收的对象信息
jmap -histo:live pid 打印堆的对象统计,包括对象数、内存大小等。特别注意,这个命令执行,JVM 会先触发一次 GC,然后再统计信息
jmap -clstats pid 打印 Java 类加载器的智能统计信息,对于每个类加载器而言,它的名称、活跃度、地址、父类加载器、加载的类的数量和大小都会被打印。此外,包含的字符串数量和大小也会被打印

-F 参数表示强制模式。如果指定的 pid 没有响应,请使用 jmap -dumpjmap -histo 选项。此模式下,不支持 live 子选项。使用示例:jmap -F -histo pid

jstack 使用

jstack 是 JDK 自带的线程堆栈分析工具,使用该命令可以查看或导出 Java 应用程序中的线程堆栈信息。

命令说明
jstack pid 输出当前 JVM 进程的线程堆栈信息