JVM介绍及参数配置

1.堆内存和非堆内存组成
堆内存:分为年轻代和老年代
年轻代:Eden区和两个存活区
Q:为什么对堆要分年轻代,老年代,伊甸园区,存活区?
A:减少FGC的频率,减少程序暂停的时间,提高性能,如果不分区,很快堆内存满了就会触发GC,对整个堆进行垃圾回收,而堆内存较大,会耗费很长时间,程序暂停时间过长,影响性能
 
2.堆内存存放的是new出来的对象和数组
非堆内存存放的是常量、静态变量、方法区、内存计数器
 
3.栈是运行时的单位,而堆是存储的单位。
栈解决程序的运行问题,即程序如何执行,或者说如何处理数据;堆解决的是数据存储的问题,而数据怎么放、放在哪儿。
栈:运行
堆:存储
 
4.JVM heap内存空间划分
分配原则:
  • 对象优先在Eden中分配,当伊甸园区满了之后会触发YGC,YGC进行寻根判断,被引用的对象进入存活区,未被引用的对象被当做垃圾回收
    当Survivor中放不下时,则由分派担保进入老年代中。
  • 大对象直接进入老年代中。 -XX:+PretenuerSizeThreshold 控制”大对象的“的大小,如果对象大小大于设置值直接放入老年代。
  • 长期存活的对象将进入老年代(默认age=15的对象叫长期存活对象,也可以用参数进行配置);
  • 动态对象年龄判定:虚拟机并不总是要求对象的年龄必须达到MaxTenuringThreshold才能晋升到老年代,如果在Survivor区中相同年龄的对象的所有大小之和超过Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无需等到MaxTenuringThreshold中要求的年龄(如age=5的对象很多,加起来大于存活区大小的一半了,那些age>=5的对象就会进入老年代);
JVM年轻代垃圾回收:
新对象首先在eden区分配空间,当eden区满时,还存活的对象将被复制到一个survivor区。当这个survivor区满时,存活对象会被复制到另一个survivor区。当第二个survivor区也满了时,存活对象被复制到老年代。 2个survivor区是完全对称的,轮流替换。
 
触发FGC的三种情况
  • 老年代满了之后,触发FGC;
  • 被显示调用的时候会触发FGC(runtime.gc()   system.gc());
  • 悲观策略(基于rmi的框架,框架中会定义隔一段时间在代码中显示调用system.gc())也会调用FGC;
  • jmap -dump 也会触发FGC
 

调优方法:
一般情况:
  • 多数的Java应用不需要在服务器上进行GC优化;
  • 多数导致GC问题的Java应用,都不是因为我们参数设置错误,而是代码问题;
  • 在应用上线之前,先考虑将机器的JVM参数设置到最优(最适合);
  • 减少创建对象的数量;
  • 减少使用全局变量和大对象;
  • GC优化是到最后不得已才采用的手段;
  • 在实际使用中,分析GC情况优化代码比优化GC参数要多得多;
GC优化的目的有两个:
  • 将转移到老年代的对象数量降低到最小;
  • 减少full GC的执行时间
为了达到上面的目的,一般地,需要做的事情有:
  • 减少使用全局变量和大对象;
  • 调整新生代的大小到最合适;
  • 设置老年代的大小为最合适;
  • 选择合适的GC收集器;
1. 不管是YGC还是Full GC,GC过程中都会对导致程序运行中中断,正确的选择不同的GC策略,调整JVM、GC的参数,可以极大的减少由于GC工作,而导致的程序运行中断方面的问题,进而适当的提高Java程序的工作效率;
2. FGC会对整个堆和非堆(包含持久带)进行垃圾回收 ;
3. YGC只会对伊甸园区和存活区进行垃圾回收;

参数名称
含义
默认值
 备注
-Xms
初始堆大小
物理内存的1/64(<1GB)
默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制.
-Xmx
最大堆大小
物理内存的1/4(<1GB)
默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制
-Xmn
年轻代大小(1.4or lator)
 
注意:此处的大小是(eden+ 2 survivor space).与jmap -heap中显示的New gen是不同的。
整个堆大小=年轻代大小 + 年老代大小 + 持久代大小.
增大年轻代后,将会减小年老代大小.此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8
-XX:NewSize
设置年轻代大小(for 1.3/1.4)
   
-XX:MaxNewSize
年轻代最大值(for 1.3/1.4)
   
-XX:PermSize
设置持久代(perm gen)初始值
物理内存的1/64
 
-XX:MaxPermSize
设置持久代最大值
物理内存的1/4
 
-Xss
每个线程的堆栈大小
 
JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K.更具应用的线程所需内存大小进行 调整.在相同物理内存下,减小这个值能生成更多的线程.但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右
一般小的应用, 如果栈不是很深, 应该是128k够用的 大的应用建议使用256k。这个选项对性能影响比较大,需要严格的测试。(校长)
和threadstacksize选项解释很类似,官方文档似乎没有解释,在论坛中有这样一句话:"”
-Xss is translated in a VM flag named ThreadStackSize”
一般设置这个值就可以了。
-XX:ThreadStackSize
Thread Stack Size
 
(0 means use default stack size) [Sparc: 512; Solaris x86: 320 (was 256 prior in 5.0 and earlier); Sparc 64 bit: 1024; Linux amd64: 1024 (was 0 in 5.0 and earlier); all others 0.]
-XX:NewRatio
年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)
 
-XX:NewRatio=4表示年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5
Xms=Xmx并且设置了Xmn的情况下,该参数不需要进行设置。
-XX:SurvivorRatio
Eden区与Survivor区的大小比值
 
设置为8,则两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10

原文地址:https://www.cnblogs.com/mululu/p/15078710.html