小小千想和您聊一聊

当前位置: 首页> 技术分享> 浅谈JVM的优化

浅谈JVM的优化

  前言

  前面我们了解过JVM中堆的GC分代回收机制,在运行Java程序时,我们可以使用JVM的参数对程序的执行过程进行优化,以达到更优的内存配置和GC配置,从而提高程序的性能和稳定性。

  JVM的参数

  JVM的参数分为三种:

  l 标准参数

  l 非标准参数

  l 非稳定参数

  标准参数以-开头,如:java -version、java -jar等,通过java -help可以查询所有的标准参数,本章不具体讨论。

  非标准参数以-X开头,是标准参数的扩展,输入:java -X可以查询所有非标准参数。我们可以通过设置非标准参数来配置堆的内存分配,常用的非标准参数有:

  -Xmn 新生代内存的最大值,包括Eden区和两个Survivor区的总和,写法如:-Xmn1024,-Xmn1024k,-Xmn1024m,-Xmn1g 。

  -Xms 堆内存的最小值,默认值是总内存/64(且小于1G),默认情况下,当堆中可用内存小于40%(这个值可以用-XX: MinHeapFreeRatio 调整,如-X:MinHeapFreeRatio=30)时,堆内存会开始增加,一直增加到-Xmx的大小。

  -Xmx 堆内存的最大值,默认值是总内存/64(且小于1G),如果Xms和Xmx都不设置,则两者大小会相同,默认情况下,当堆中可用内存大于70%时,堆内存会开始减少,一直减小到-Xms的大小;

  整个堆的大小=年轻代大小+年老代大小,堆的大小不包含持久代大小,如果增大了年轻代,年老代相应就会减小,官方默认的配置为年老代大小/年轻代大小=2/1左右;

  建议在开发测试环境可以用Xms和Xmx分别设置最小值最大值,但是在线上生产环境,Xms和Xmx设置的值必须一样,原因与年轻代一样——防止抖动;

  -Xss 每个线程的栈内存,默认1M,一般来说是不需要改的。

  -Xrs 减少JVM对操作系统信号的使用。

  -Xprof 跟踪正运行的程序,并将跟踪数据在标准输出输出;适合于开发环境调试。

  -Xnoclassgc 关闭针对class的gc功能;因为其阻止内存回收,所以可能会导致OutOfMemoryError错误,慎用;

  -Xincgc 开启增量gc(默认为关闭);这有助于减少长时间GC时应用程序出现的停顿;但由于可能和应用程序并发执行,所以会降低CPU对应用的处理能力。

  -Xloggc:file 与-verbose:gc功能类似,只是将每次GC事件的相关情况记录到一个文件中,文件的位置最好在本地,以避免网络的潜在问题。

  非稳定参数,以-XX开头,官方介绍这些参数是不稳定的,但往往在进行JVM优化时,这些参数能起到重要作用。

  非稳定参数分为三类:

  l 性能参数:用于JVM的性能调优和内存分配控制,如内存大小的设置;

  l 行为参数:用于改变JVM的基础行为,如GC的方式和算法的选择;

  l 调试参数:用于监控、打印、输出jvm的信息;

  使用方法有三种:

  l -XX:+<选项> 启用选项

  l -XX:-<选项> 不启用选项

  l -XX:<选项>=<数值> 给选项设置一个数字类型值,如 32k, 1024m, 2g

  l -XX:<选项>=<字符串> 给选项设置一个字符串值,如

  -XX:HeapDumpPath=./dump.core

  常用性能参数:


  常用行为参数:


  常用调试参数:


  常见的配置

  典型的JVM配置:

  java -Xmx2048m -Xms2048m -Xmn2g -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0

  参数说明:

  -Xmx2048m :堆的最大内存为2048M。

  -Xms2048m :堆的最小内存为2048m。最大内存和最小内存配置相同,以避免每次垃圾回收完成后JVM重新分配内存也就是抖动。

  -Xmn2g:设置年轻代大小为2G。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,官方推荐配置为整个堆的3/8。

  -Xss128k:设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。

  -XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与年老代的比例(除去持久代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5

  -XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的大小比例。设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6

  -XX:MaxPermSize=16m:设置持久代大小为16m。

  -XX:MaxTenuringThreshold=0:设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概率。

  GC的选择

  JVM中有三种垃圾收集器:

  l 串行收集器

  性能不高,只适合数据不多的应用

  l 并行收集器

  能达到较高的吞吐量,适用于科学技术和后台处理等

  l 并发收集器

  能保证系统的响应时间,减少垃圾收集时的停顿时间。适用于应用服务器、电信领域等

  典型的JVM配置

  1)

  java -Xmx2048m -Xms2048m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20

  说明:

  -XX:+UseParallelGC:选择垃圾收集器为并行收集器。此配置仅对年轻代有效。即上述配置下,年轻代使用并发收集,而年老代仍旧使用串行收集。

  -XX:ParallelGCThreads=20:配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。

  2)

  java -Xmx2048m -Xms2048m -Xmn2g -Xss128k -XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC

  -XX:+UseConcMarkSweepGC:设置年老代为并发收集。

  -XX:+UseParNewGC: 设置年轻代为并行收集。可与CMS收集同时使用。JDK5.0以上,JVM会根据系统配置自行设置,所以无需再设置此值。

  调优总结

  响应时间优先的应用

  将年轻代尽量设置大,直到接近系统的最低响应时间限制(根据实际情况选择)。在此种情况下,年轻代收集发生的频率也是最小的。同时,减少到达年老代的对象。

  年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数。如果堆设置小了,可以会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间。

  吞吐量优先的应用

  将年轻代尽设置大量,可能到达Gbit的程度。因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用。

  一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象。

上一篇:HTML5工具初识之网页编辑器

下一篇:菜鸟Vue学习笔记(三)

QQ技术交流群

千锋Java开发官方①群
811099962

加入群聊