JVM性能调优

Java从诞生之初就一直被诟病性能不如C/C++。究其原因,最主要是因为Java程序是运行在JVM虚拟机之上,而C/C++是运行在物理机之上。对于Java程序而言,哪怕是最简单的 HelloWorld 程序都需要先运行一个JVM程序。这意味着要它至少要多出一个类加载程序、字节码解析执行程序以及GC程序等。不过,虽然牺牲了一些运行效率,但是Java通过 JVM 实现了其 “Write Once, Run Anywhere” 的伟大构想。

与物理机相比,虚拟机是通过软件实现的,意味着它有更大的“可调”空间。也因此才有 JVM 性能调优这一课题。简单讲就是为具体的Java程序,调配一台最适合它跑的机器。对C/C++工程师来说,编译优化是必修的内功。同样地,对Java工程师而言,JVM调优也是必修的内功。另外值得一提的是,JVM作为一台虚拟机可不是只能运行Java程序。其他语言如Kotlin、Scala、Clojure、Groovy也都运行在JVM之上。所以JVM调优也是使用这些语言的工程师们的必修技能。

 

选择JVM

其实没什么好选择的,服务端Java应用一般都运行在 HotSpot VM之上。但还是有必要了解一下 JVM 族谱(如下图所示),这有助我们提升Java内功。如果从事其他领域的 Java 开发很可能就会面临 JVM 的选择。详细内容可阅读《JVM简介》

HotSpot VM 是JDK默认提供的JVM,Java企业级应用一般都是运行在此JVM上。它名称中的 HotSpot 是指热点代码探测技术。正是这项技术让它在众多高性能JVM中脱颖而出,成为目前最广泛使用的JVM。下文关于服务端JVM的性能调优都是针对HotSpot VM而言。

 

JVM性能调优目标

前面提到Java程序在运行时,除了本身实现的作业程序外,还需要同时运行类加载程序、字节码解析执行程序、JIT编译程序、GC程序等这些JVM内核程序。JVM性能调优的目标就是减少内核程序的开销,把计算资源尽可能让渡给作业程序。其中最主要的是对GC程序的调优。

除GC程序外的其他JVM内核程序暴露的配置参数很少,它们的性能都是JVM内部实现决定的。不同 JVM 的对比主要就是看这部分的性能差别。比如 HotSpot 的最大优势就是通过JIT机制将探测到的热点代码即时编译成机器码执行,从而提高运行效率。这一部分值得提一下的是 -server 和 -client 两种运行模式的选择。服务端JVM显然应该使用-server模式,它比client模式启动过程慢,但是启动后整体运行效率要比client模式高10倍左右。如果不指定,JVM默认会根据物理机的配置来判断是server还是client模式。建议生产环境强制指定server模式。开发环境,如果觉得Java服务启动太慢,可以考虑用client模式启动。

GC是最能影响作业程序的JVM内核程序,性能调优的核心就是针对GC的优化。目标是减少由GC引起的作业程序停顿时间,特别的是减少Full GC的时间和频次。一般GC时间大于1秒就需要进行优化了。

 

JMM与GC机制

GC优化首先需要了解 JVM 的内存模型(JMM)以及GC过程。关于这块知识点可以阅读《JVM简介》。这里探讨下为什么 JVM 要对内存进行分代管理。简单讲是由一对矛盾决定的。

内存是程序运行的必需资源,对程序而言,最完美的情况是内存资源无限大,可以尽情索取。显然这是不可能,内存资源是有限的,需要做精细化管理才能提高内存的使用效率,从而更好地运行JVM上的作业程序。但是“管理”本身也是一个程序,它开销大也会影响作业程序。另一个极端是GC做到极致,能非常及时地找到并回收内存,整理内存碎片。这样内存使用效率最高,但整个CPU资源都会耗在GC程序上。正是内存管理成本和使用效率的矛盾,导致了JVM采用分代回收来平衡不同生命期对象的内存使用管理。

 

JVM性能诊断和监控工具

JVM调优首先得知道性能卡点在何处,诊断出病因才好对症下药。JDK自带了如下8款工具,可帮助我们定位问题。

jps工具类似Linux的ps命令,用来打印主机中的所有JVM进程。经常用的参数选项有-mlv。-m 输出传入main方法的参数;-l 输出main类或Jar的全名;-v 输出JVM的启动参数。

jstat 工具用于监视虚拟机各种运行状态信息,可以显示本地或远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。jstat 命令有丰富的选项来显示不同的信息,可自行百度查看使用方法。

jstack 工具用于生成虚拟机当前时刻的线程快照。线程快照是JVM内每一条线程正在执行的方法堆栈的集合,主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。

jinfo 工具用来实时地查看和调整虚拟机各项参数。

jmap 用于生成堆快照dump文件。如果不使用jmap命令,可以使用-XX:+HeapDumpOnOutOfMemoryError参数,当虚拟机发生内存溢出的时候可以产生快照。或者使用kill -3 pid也可以产生。jmap的作用并不仅仅是为了获取dump文件,它可以查询finalize执行队列,java堆和永久代的详细信息,如空间使用率,当前用的哪种收集器。

jhat 用于分析内存转储快照。这个工具功能比较简陋,运行起来也比较耗时,不推荐使用。可用MAT工具替代。

jconsole 是一个JVM图形化监视工具,可以以图表化的形式显示各种数据,并可通过远程连接监视远程的服务器VM。Java程序需要开JMX才能通过jconsole连接查看。

jvisualvm 这个工具也很强大。它同jconsole都是一个基于图形化界面的,可以查看本地及远程JVM的GUI监控工具。jvisualvm界面更美观一些,数据更实时。

 

JVM调优参数

JVM作为一台虚拟机,提供了丰富的启动参数来对JVM运行过程进行控制。这些参数可以分成三类:

  1. 标准参数(-):所有JVM都必须实现的功能,且向后兼容。例如-h, -version, -server;

  2. 非标准参数(-X):默认JVM会实现,但不保证所有JVM都会实现的参数,且不保证向后兼容。例如-Xms, -Xmx, -Xmn;

  3. 非Stable参数(-XX):此类参数各个JVM实现可能会有所不同,将来可能随时取消,需要慎重使用。例如-XX:PermSize, -XX:NewRatio。

服务端Java应用使用 HotSpot VM,一般对它的性能调优会使用以下这些参数。

 

延伸阅读

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值