JVM 调优

作者: Java耕耘者 | 来源:发表于2019-08-21 13:52 被阅读1次

-XX:AutoBoxCacheMax

-XX:+AlwaysPreTouch

CMSInitiatingOccupancyFraction

MaxTenuringThreshold

ExplicitGCInvokesConcurrent

-Xmx, -Xms

NewRatio

概述

公司的江南白衣写了一篇关键业务系统的JVM参数推荐(2016热冬版)的文章,大牛的文章总是需要细细品读。这篇文章介绍大量的JVM调优参数,内容也比较多,本文只是列出我自己能理解的一些参数,暂时理解不了的参数就只能等以后自己实力到家了,再慢慢补充上来。

性能调优参数

-XX:AutoBoxCacheMax

JAVA进程启动的时候,会加载rt.jar这个核心包的,rt.jar包里的Integer自然也是被加载到JVM中,Integer里面有一个IntegerCache缓存,如下:

privatestaticclassIntegerCache{

staticfinalintlow = -128;

staticfinalinthigh;

staticfinalInteger cache[];

static{

// high value may be configured by property

inth =127;

String integerCacheHighPropValue =

sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");

if(integerCacheHighPropValue !=null) {

inti = parseInt(integerCacheHighPropValue);

i = Math.max(i,127);

// Maximum array size is Integer.MAX_VALUE

h = Math.min(i, Integer.MAX_VALUE - (-low) -1);

}

high = h;

cache =newInteger[(high - low) +1];

intj = low;

for(intk =0; k < cache.length; k++)

cache[k] =newInteger(j++);

}

privateIntegerCache(){}

}

IntegerCache有一个静态代码块,JVM在加载Integer这个类时,会优先加载静态的代码。当JVM进程启动完毕后, -128 ~ +127 范围的数字会被缓存起来,调用valueOf方法的时候,如果是这个范围内的数字,则直接从缓存取出。

超过这个范围的,就只能构造新的Integer对象了。

publicstaticIntegervalueOf(inti){

assertIntegerCache.high >=127;

if(i >= IntegerCache.low && i <= IntegerCache.high)

returnIntegerCache.cache[i + (-IntegerCache.low)];

returnnewInteger(i);

}

因此可以根据实际情况把AutoBoxCacheMax的值设置的大写,比如江南白衣推荐的

-XX:AutoBoxCacheMax=20000

-XX:+AlwaysPreTouch

JAVA进程启动的时候,虽然我们可以为JVM指定合适的内存大小,但是这些内存操作系统并没有真正的分配给JVM,而是等JVM访问这些内存的时候,才真正分配,这样会造成以下问题。

1、GC的时候,新生代的对象要晋升到老年代的时候,需要内存,这个时候操作系统才真正分配内存,这样就会加大young gc的停顿时间;

2、可能存在内存碎片的问题。

可以在JVM启动的时候,配置

-XX:+AlwaysPreTouch

参数,这样JVM就会先访问所有分配给它的内存,让操作系统把内存真正的分配给JVM.后续JVM就可以顺畅的访问内存了。

GC参数

JAVA 1.7用的垃圾收集算法还是CMS,下文提到的参数都是针对CMS的。

CMSInitiatingOccupancyFraction

之前写过一篇java垃圾回收算法之-CMS(并发标记清除),里面提到垃圾收集线程会跟应用的线程一起并行的工作,万一垃圾收集线程在工作的时候,老年代内存不足怎么办?因此最好还是提前启动CMS来收集垃圾(CMS GC)。

可以通过设置

CMSInitiatingOccupancyFraction=75

那么当老年代堆空间的使用率达到75%的时候就开始执行垃圾回收,CMSInitiatingOccupancyFraction默认值是92%,这个就太大了。

CMSInitiatingOccupancyFraction参数必须跟下面两个参数一起使用才能生效的。

-XX:+UseConcMarkSweepGC

-XX:+UseCMSInitiatingOccupancyOnly

MaxTenuringThreshold

新生代是使用copy算法来进行垃圾回收的,可以参看

java垃圾回收算法之-coping复制

默认情况下,当新生代执行了15次young gc后,如果还有对象存活在Survivor区中,那么就可以直接将这些对象晋升到老年代,但是由于新生代使用copy算法,如果Survivor区存活的对象太久的话,Survivor区存活的对象就越多,这个就会影响copy算法的性能,使得young gc停顿的时间加长,建议设置成6。

-XX:MaxTenuringThreshold=6

ExplicitGCInvokesConcurrent

如果系统使用堆外内存,比如用到了Netty的DirectByteBuffer类,那么当想回收堆外内存的时候,需要调用

System.gc()

而这个方法将进行full gc,整个应用将会停顿,如果是使用CMS垃圾收集器,那么可以设置

-XX:+ExplicitGCInvokesConcurrent

这个参数来改变System.gc()的行为,让其从full gc --> CMS GC,CMS GC是并发收集的,且中间执行的过程中,只有部分阶段需要stop the world。

注意:设置了ExplicitGCInvokesConcurrent,那就不要设置DisableExplicitGC参数来禁掉System.gc()。

内存参数

-Xmx, -Xms

这两个一般都是设置4个g

NewRatio

GC最多的还是发生在新生代的young gc,所以可以提高一下新生代在整个堆的占用比例,建议设置为对半分,尽量避免young gc

-XX:NewRatio=1

关注公众号领资料

搜索公众号【Java耕耘者】,回复【Java】,即可获取大量优质电子书和一份Java高级架构资料、Spring源码分析、Dubbo、Redis、Netty、zookeeper、Spring cloud、分布式等视频资料

相关文章

网友评论

    本文标题:JVM 调优

    本文链接:https://www.haomeiwen.com/subject/gfvbsctx.html