关闭

java垃圾回收之Minor GC和Major GC

标签: minor gcfull gc
1427人阅读 评论(0) 收藏 举报
分类:

jvm采用分代内存回收,而jvm参与内存回收的区域主要包含堆(主要存放对象)和持久代(主要存放class信息和被final修饰的常量);
而堆内存又被分为年轻代和年老代,年轻代又被分为eden区和survivor区,默认比率为8:1.
针对年轻代垃圾回收的机制被称为minor gc,针对年老代和持久代垃圾回收的机制被称为full gc。


1.问:minor gc什么时候被触发?
触发minor gc的关键在于:eden区内存不足。造成eden区内存不足的原因:由于java对象大部分都是朝生夕死(java局部对象),而死掉的对象就需要在合适
的时机被jvm回收,这里就涉及到根搜索算法,java对象的关联关系其实就是一个树形结构,从根到叶子节点遍历,死掉的对象也就和根断开了连接关系,
没有死掉的对象也会由于minor gc被强制断开关系。


2.问:minor gc执行过程?
由于minor gc是针对年轻代,年轻代又分eden和suivivor区,
suivivor区又分from和to,在发生minor gc的时候,jvm会对对象进行回收(涉及到eden和suivivor的from),为什么
只涉及eden和from?因为此时to是空的。这里就要牵扯到from和to的转换问题。
在GC开始的时候,对象只会存在于Eden区和名为“From”的Survivor区,Survivor区“To”是空的。
紧接着进行GC,Eden区中所有存活的对象都会被复制到“To”,而在“From”区中,仍存活的对象会根据他们的年龄值来决定去向。
年龄达到一定值(年龄阈值,可以通过-XX:MaxTenuringThreshold来设置)的对象会被移动到年老代中,没有达到阈值的对象会被复制到“To”区域。
经过这次GC后,Eden区和From区已经被清空。这个时候,“From”和“To”会交换他们的角色,也就是新的“To”就是上次GC前的“From”,
新的“From”就是上次GC前的“To”。不管怎样,都会保证名为To的Survivor区域是空的。Minor GC会一直重复这样的过程,直到“To”区被填满,
“To”区被填满之后,会将所有对象移动到年老代中。


3.问:full gc什么时候被触发?
(1)年老代内存不足;(2)持久代内存不足;(3)统计得到的Minor GC晋升到旧生代的平均大小大于旧生代的剩余空间,
这是一个较为复杂的触发情况,Hotspot为了避免由于新生代对象晋升到旧生代导致旧生代空间不足的现象,在进行Minor GC时,做了一个判断,
如果之前统计所得到的Minor GC晋升到旧生代的平均大小大于旧生代的剩余空间,那么就直接触发Full GC。
(4) CMS GC时出现promotion failed和concurrent mode failure
对于采用CMS进行旧生代GC的程序而言,尤其要注意GC日志中是否有promotion failed和concurrent mode failure两种状况,当这两种状况出现时可能会触发Full GC。
promotion failed是在进行Minor GC时,survivor space放不下、
对象只能放入旧生代,而此时旧生代也放不下造成的;
concurrent mode failure是在执行CMS GC的过程中同时有对象要放入旧生代,而此时旧生代空间不足造成的。
应对措施为:增大survivor space、旧生代空间或调低触发并发GC的比率,但在JDK 5.0+、6.0+的版本中有可能会由于JDK的bug29导致CMS在remark完毕
后很久才触发sweeping动作。对于这种状况,可通过设置-XX: CMSMaxAbortablePrecleanTime=5(单位为ms)来避免。
(5)调用System.gc的时候,虽然这个过程不可控。


至于full gc触发过程?这个过程没有特殊之处,不做详解。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:217704次
    • 积分:3474
    • 等级:
    • 排名:第9517名
    • 原创:98篇
    • 转载:98篇
    • 译文:0篇
    • 评论:25条
    最新评论