Java虚拟机内存回收

感谢周志明所著的《深入理解Java虚拟机》一书。下面附上了一些我自己的理解。

当说到java堆的垃圾回收,就会想到它的内存分配和回收算法。下面就详细介绍我的理解。
一、内存分配。
1.新对象优先分配到新生代Eden区中
    内存优先分配在新生代Eden区中,该区域经过一次GC,大概会有98%新对象被回收掉,剩余的进入Survivor区中。

2.大对象直接进入老年代
    大对象是指需要大量连续内存空间的Java对象,例很长很长的字符串以及数组。
    大对象对于虚拟机内存分配时一个噩耗,特别是短命的大对象,由于新生代采用复制算法, 如果分配到新生代,就会导致在Eden区以及两个Survivor中频繁的发生大量内存复制,极大影响CPU的处理效率。所以通过虚拟机设置,当大于设定的值时,直接进入老年代。

3.长期存活的对象将进入老年代
    如果一个对象经过多次Minor GC过后,如果还是没有被回收掉,我们就认为当前对象是长期稳定存在的,随着达到设定的年龄(默认为15岁)将晋升为老年代。

二、对象存活算法
    当要进行垃圾回收时,肯定需要先判断当前对象是否存活,下面就是常用的两种算法
1.引用计数法
    给每个对象添加一个引用计数器,每当有一个地方引用它的时候,计数器的值就加1,每当引用失效时,计数器值就减1;任何引用计数器值为0的对象都可以被回收。
    虽然引用计数器的实现简单,效率也也高,但是它有一个严重的缺陷,当两个对象只存在之间的相互引用时,由于两个对象引用计数器值都不为0,这个算法就无法通知GC收集器回收它们。

2.可达性分析算法
    由于上面引用计数法的缺陷,就产生了可达性分析算法。
    这个算法的思想就是通过一系列的被列为“GC Roots”的对象作为起始点,从这些结点向下搜索,搜索所走的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,判断当前对象时不可用的,应该被回收。
    被可达性算法标记为不可达的对象,并非马上就被回收,至少要经过两次标记过程才会回收,可以在finalize()方法中重新建立引用链来拯救对象。但是不建议使用finalize()方法,因为finilize()在F-Queue队列中,如果finalize()方法执行缓慢或者发生死循环会引起整个垃圾回收系统崩溃。
    能作为GC Roots的对象包括下面几种:
(1)虚拟机栈(栈中的本地变量表)中引用的对象。
(2)方法区中类静态属性引用的对象
(3)方法区中常量引用的对象
   
特别注意:方法区同样适用的是上述的算法,判断的对象是常量池中对象和 类的卸载。

三、垃圾回收算法
1.标记-清除算法
    算法分为标记和清除两个阶段,先将要回收的对象,在标记完成后统一回收所有被标记的对象。
    缺点:一是效率问题,标记和清除两个过程效率都不高;二是空间问题,该算法产生的是大量不连续的内存碎片,太多碎片可能导致在有较大对象将要分配时,无法找到足够的连续内存而不得不提前触发下一次的垃圾回收动作。

2.复制算法
    将内存分为可用的大小相等的两块区域,每次只能使用一块,当一块的内存用完了,将还存活的对象复制到另一块上面,再把已用过的这一块内存空间一次清理掉。用于新生代,老年代一般不采用。
    当前的新生代算法就采用的复制算法,由于新生代中对象有98%是可回收对象,所以分配的区域不是按照1:1的比例来划分,而是按照Eden区:Survivor 1:Survivor 2为8:1:1的方式划分,只有10%会被浪费。将Eden区和一块Survivor区还存活的对象一次性复制到另一块Survivor区上,最后清理掉Eden区和刚才用过的Surbvivor区。
    优点:不用考虑标记-清除算法产生内存碎片的情况。
    缺点:内存代价比较高,可用能存只有一半。在对象存活率比较高的情况下,进行较多的复制操作,效率将会变低。

3.标记-整理算法
    标记流程和标记-清除算法一致,区别在于它不是标记后直接清除,而是会将存活的对象移动到一端,然后清理掉存活区域以外的内存。常用于老年代回收。老年代中对象存活率高而且没有空间分配担保,不能采用复制算法。

4.分代收集算法
    堆一般分为新生代和老年代,根据各个年代的特点分别选用上述三种合适的收集算法。例,少量对象存活就选用复制算法;对象存活率高,就必须选用“标记-清除”或者“标记-整理”算法来进行回收。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值