`

JVM参数浅析

 
阅读更多

后续的JVM参数分析都在这里整理

#-Xss1m 设置每个线程的堆栈大小

#-XX:+UseParNewGC 设置年轻代为并行收集。

#-XX:+UseConcMarkSweepGC 设置并发收集器

#-XX:+CMSParallelRemarkEnabled 表示并行remark

#-XX:+UseCMSCompactAtFullCollection  打开对年老代的压缩。可能会影响性能,但是可以消除碎片

#-XX:+UseFastAccessorMethods 原始类型的快速优化

#-XX:+UseCMSInitiatingOccupancyOnly 使用手动定义初始化定义开始CMS收集

#-XX:+UseCompressedOops

#-XX:-ReduceInitialCardMarks

#-XX:CMSInitiatingOccupancyFraction=75

#-XX:SurvivorRatio=3   survivor和eden的比值为1:3  

#-XX:+DisableExplicitGC

#-XX:-UseAdaptiveSizePolicy

 

1.-Xms100m -Xmx100m

   ms:minus即最小内存,jvm启动的时候初始化内存,如果ms和mx不相同则jvm的内存会根据使用情况动态调整,一般设置两个值相同。

  ms,mx的内存是指young和tenured两块的内存,有些blog说这个是整个jvm的内存包含permgen的内存,实际是不正确的。可以通过jstat -gc来计算出来的,详情见截图。

  S0C+S1C+EC+OC=102400也就是100M

    

 


 

 

 

 2.-Xmn 指定young内存的大小 

    指定-Xmn50M 通过计算就可以得出young和old区域分别是50M

   

 

 

 

 3.-XX:PermSize  -XX:MaxPermSize

   -XX:PermSize jvm初始化永久代的大小,-XX:MaxPermSize jvm最大的永久代大小。

   此处设置100M可以看出来永久代的确是100M。young和tunured堆内存不受影响。


 

 

4.-XX:NewRatio=4

   设置young和tenured的比值1:4   100M的话则tenured的内存为80M。
   

 



 

 

5.-XX:SurvivorRatio=3

   survivor和eden的比值为1:3   所以survivor占用内存的1/5。

   

 



 

 6.-XX:MaxTenuringThreshold=n

  设置对象在young区域复制的次数,超过这个次数存活的对象拷贝至old区域。

   验证这个参数,过程还是挺纠结的,先把纠结的过程记录下吧,测试代码如下。

   

public class TestOOM {

	public static void main(String[] args) throws InterruptedException {
		
		List list=new ArrayList();
		OOM oom=new OOM();
		Thread.sleep(20*1000);
		for(int i=0;i<15;i++){
	//		System.out.println(i);
	//		list.add(new OOM());
	    OOM xx=new OOM();
	    xx=null;
			Thread.sleep(2*1000);
		}
		
	}
	
}

class OOM{
	
	byte[] bytes=new byte[1024*1024*8];
	
}

 

     第一次尝试,

     java -Xms100M -Xmx100M -Xmn30M -XX:SurvivorRatio=1  TestOOM

     heap分配100M,young 30M XX:SurvivorRatio=1这样eden,survivor都是10M了。预想第一次分配的8M对象进入Eden,后面再分配对象的时候肯定会出现minor gc,这样不断的分配对象,不断的设置成null,这样就会不断的出现minor gc超过一定的次数就会进入tenured区域。可是发现实际的结果还是与想象的差别很大,因为对象直接就在tenured区域中分配了,而且tenured区域满的时候开始minor gc了。

      

 

    确实大对象会直接进入tenured区域,这就引出了另外一个参数, -XX:PretenureSizeThreshold,这个参数的值只能是B,字节。

    第二次尝试,可以设置超过10M的对象才能进入tenured区域。

    java -Xms100M -Xmx100M -Xmn30M -XX:SurvivorRatio=1  -XX:PretenureSizeThreshold=10485760  TestOOM

     不过发现这个参数不灵光,这个8M的对象还是直接进入了tenured区域。也是上面的现象tenured区域满的时候开始minor gc了。

     

  

      哎,这个参数不灵光啊,突然又有个新的想法,为何不把tenured区域的参数设置小于8M,这样用户不就进不去了,这样不就一直在young区域gc了吗,此时小小得意了一下,心想这不就没有问题了。

 

     第三次尝试,

     java -Xms35M -Xmx35M -Xmn30M -XX:SurvivorRatio=1  -XX:MaxTenuringThreshold=10   TestOOM

     

 

   虽然这次按照预想的在young区域进行minor gc但是又有新的问题啦,minor gc 6次之后竟然报oom。

 

   所以怀疑是不是jvm内部机制如果minor gc 6次内存没有减的话就会报错,于是乎猜想如果-XX:MaxTenuringThreshold=3是不是三次之后就会将对象进入tenured区域,但是此时发现tenured区域没有足够的空间此时会抛oom错误呢。

    

    第四次尝试,

    java -Xms35M -Xmx35M -Xmn30M -XX:SurvivorRatio=1  -XX:MaxTenuringThreshold=3   TestOOM

    还是以失败告终啊,竟然还是minor gc 6次之后才报错啊,是在不明白了,有大神给解读下这是为什么吗?

 

 

  • 大小: 4 KB
  • 大小: 3.6 KB
  • 大小: 1.1 KB
  • 大小: 3.5 KB
  • 大小: 1.4 KB
  • 大小: 5.6 KB
  • 大小: 1 KB
  • 大小: 3.1 KB
  • 大小: 1 KB
  • 大小: 3 KB
  • 大小: 20.8 KB
  • 大小: 20.6 KB
  • 大小: 11.4 KB
  • 大小: 2.9 KB
1
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics