前言
1、对象优先在Eden分配(如果小于Survivor,先进入Survivor)
复制算法还记得吧,就是说的商业虚拟机关于新生代的垃圾收集就是采用的复制算法 将内存分为3分分别为8:1;1 那么Eden 就代表着8份
1 |
|
1.1、测试
1 | package com.hlj.jvm.GC; |
运行观察GC
关键性解释:当分到allocation4的时候回发生一次Minor GC
当运行到allocation4的时候,我们已经在新生代的Eden中添加了6M的内存,如果再添加4M的话,很明显会超出新生代所给的Eden最大范围8,这个时候,就会提前发生Minor GC(这三个对象是存活的,不是清除哦) ,GC的时候还会发现妈的巴子Survivor才1M,明显放不下,所以只能通过分配担保机制提前转移到老年代中去了。精彩,老子想鼓鼓掌 。哈哈
那么这个时候 allocation4 所需要的4M就放到了Elen中,老年代中放6M(被allocation1、allocation2、allocation3占用) 具体看下面日志就知道了
6651k->148k(9216k)Gc前新生代从6M(Edeb)->GC后148K(Survivor)
下面表示的在发生GC之后的内存分布,一定要注意,这里仅仅是自己触发,并没有进行虚拟机回收的日志,(没有full gc也就是不执行老年代GC,)
8192*51% = 4M,就是说有4M放到了Eden中
1024*14% = 148k,表示最后survivor中放置148K
下面 space 10240k 60% 表示在老年代中放置了6M(没错)
2、大对象直接进入老年代
所谓的大对象其实就是需要大量连续内存空间的JAVA对象,最典型的就是那种很长的字符串和数组,大对象对于虚拟机来说是一个坏消息,(更要命的是遇到短命大对象,所以写程序的时候要尽量避免) 经常出现大对象,容易导致内存还有很多空间,就提前触发垃圾收集来获取足够的空间(就比如1中的)
JAVA虚拟机提供 XX:PretenureSizeThreshold
参数用来设置大于它的直接放到老年代分配,这样的目的是避免了Eden和两个Survivor区直接发送大量的内存复制
1 | -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:PretenureSizeThreshold:3145728 |
1 | /** |
3、长期存活的对象将进入老年代
虚拟机采用的是分代收集算法,java虚拟机就能够知道哪些在新生代中,哪些在老年代中。其实他对每个对象的年龄都定义了一个计数器,当对象在Ede出生并经历过地第一次Minor GC后能够进入Survivor区,会将它的年龄设置为1.每度过一次Minor GC 它的年龄就会增加1.知道增加到一定程度,默认为15。确实挺老的。
通过参数自行设置年龄大小 -XX:MaxTenuringThreshold=1
1 | /** |
4、动态对象年龄判断
为了更好适应不同程序上的内存状态,虚拟机并不是永远要求达到MaxTenuringThreshold
,如果在Survivor空间中相同年龄所有对象的大小总和大于Survivor的一半,年龄大于它的直接进入老年代。无需等待
1 |
|
5、空间分配担保
1 | HandlePromotionFailure 不再使用 |
在发生Minor GC之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象总空间,如果这个条件成立,那么Minor GC可以确保是安全的。
如果不成立,则虚拟机会查看HandlePromotionFailure设置值是否允许担保失败。如果允许,那么会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试着进行一次Minor GC,尽管这次Minor GC是有风险的;如果小于,或者HandlePromotionFailure设置不允许冒险,那这时也要改为进行一次Full GC。
如果出现了HandlePromotionFailure失败,那就只好在失败后重新发起一次Full GC。虽然担保失败时绕的圈子是最大的,但大部分情况下都还是会将HandlePromotionFailure开关打开,避免Full GC过于频繁,参见如下代码,请读者在JDK 6 Update 24之前的版本中运行测试。
在JDK 6 Update 24之后,这个测试结果会有差异,然源码中还定义了HandlePromotionFailure参数,但是在代码中已经不会再使用它。JDK 6 Update 24之后的规则变为只要老年代的连续空间大于新生代对象总大小或者历次晋升的平均大小就会进行Minor GC,否则将进行Full GC。