JVM知识总结--内存分配策略

对象的内存分配主要是在堆上进行的,也有可能在JIT编译后被拆散为标量类型并间接的在栈上分配,对象主要分配在Eden区,如果启动了TLAB,则优先分配到TLAB上,少数情况下可能直接分配到老年代中;总的来说对象的分配有大致的规则和模式,但无一定之规,具体的分配逻辑与使用的GC收集器类型和配置的JVM参数都会有关系。

Minor GC 和 Full GC

  1. Minor GC:发生在新生代的垃圾收集动作,频率高、速度快;
  2. Full GC/Major GC:发生在老年代的GC,通常会伴随至少一次的Minor GC,一般会比Minor GC慢10倍以上;

最普遍的几条内存分配原则如下:

  1. 对象优先在Eden区分配:当Eden区没有足够的空间时,虚拟机会发起一次Minor GC;
  2. 大对象直接进入老年代:大对象是指需要大量连续内存空间的对象,典型的大对象就是很长的字符串或数组,虚拟机提供了-XX:PretenureSizeThreshold参数(仅针对Serial和Par New收集器有效),大于此设置值的对象会直接放入老年代;
  3. 长期存活的对象将进入老年代:为了在内存回收时识别哪些对象放在年轻代,哪些放在老年代,VM给每个对象定义了一个对象年龄计数器(Age),对象在第一次Minor GC后仍存活并被移动到Survivor中后Age会被设为1,以后每经过一次Minor GC age都会加1,age增加到15(默认值)后,对象会被移动到老年代中,对象晋升到老年代的age阈值可以通过-XX:MaxTenuringThreshold来设置;
  4. 动态对象年龄判定:为了更好的适应不同程序的内存情况,如果在Survivor空间中相同年龄的所有对象大小总和大于Survivor空间的一半,则年龄大于等于此年龄的对象可以忽略3中的配置直接进入老年代;
  5. 空间分配担保:在发生Minor GC前,vm会先检查老年代的最大可用连续空间是否大于新生代对象的总空间,如果小于,虚拟机会查看HandlePromotionFailure是否允许担保失败,如果允许,vm会继续检查老年代的最大可用连续空间是否大于历次晋升到老年代的对象的平均大小,如果大于,将会尝试进行一次Minor GC,如果小于或HandlePromotionFailure设置为不允许失败,会先进行一次Full GC,总的来说,这是为了保证在Minor GC发生时老年代有足够的连续空间存放可能会从新生代晋升来的对象而采取的一项措施,为了避免频繁的Full GC,HandlePromotionFailure通常会被设置为True;另外,在JDK 6 Update 24之后,HandlePromotionFailure参数不再生效,只要老年代的可用连续空间大于新生代对象总和或历次晋升的平均大小,就会进行Minor GC,否则进行Full GC。

猜你喜欢

转载自my.oschina.net/u/580449/blog/2986184