java虚拟机之垃圾回收


1. 判断哪些对象可以回收 

堆中几乎放着java世界中的所有的对象实例,垃圾收集器在对堆进行回收前,第一件事就是要确定这些对象哪些还“存活”着,哪些已经“死去”(即不可能再被任何途径使用的对象)。判断对象是否存活的算法一般有两种:引用计数算法和根搜索算法。因为在java中是用根搜索算法来判断对象是否已死的。这里主要介绍下根搜索算法。 

根搜索算法的基本思路就是通过一系列的名为“GC Roots”的对象作为起始点,从这个节点开始向下搜索,搜索所有走过的路径称为引用链,当一个对象到GC Roots 没有任何引用链相连时,就证明次对象不可用的。 

在java语言里,可以作为GC Roots的对象包括以下几种: 
A. 栈中的引用的对象。 
B. 方法区中的类静态属性引用的对象。 
C. 方法区中的常量引用的对象。 
D. 本地方法栈中JNI的引用的对象。 

2. 垃圾收集算法 

1)标记-清除 
这是最基础的垃圾收集算法,算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。它的主要缺点有两个:一个是效率问题,标记和清除效率都不高;另一个是空间问题,标记清除后会产生大量不连续的内存碎片,空间碎片太多可能会导致分配大对象是没有足够的大的连续空间,而触发另一次垃圾收集动作。 

2)复制算法 
为了解决效率问题,有了“复制”的算法,他将可用内存分为大小相同两块。每次只用一块,当一块空间用完了,就将还存活的对象复制到另一块上,然后将刚使用过的内存空间一次清理掉。这样就把原来的内存缩小到原来的一半,代价太贵了点。实际上,新生代中的对象98%都是朝生夕死,所以不需要按1:1的比例来分内存,而是将内存分为一块较大的Edn空间和两块较小的Survivor空间,每次使用Edn空间和其中一块Survivior空间。当回收时,将Edn和Survivor中还存活的对象一次性的拷贝到另一块Suivivior中,最后清理掉Edn和刚用过的Survivor空间。 

3)标记-整理 
由于老年代中的对象生存周期都叫长,有人提出“标记-整理”算法,标记过程和“标记-清理”一样,但在清除已死对象的同时会对存活对象进行整理,这样可以减少碎片空间。 

4)分代收集 
根据对象的存活周期不同,一般将java堆分为新生代和老年代,这样就可以根据各个年代采用最适合的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就用复制算法,只要少量复制成本就可以完成收集。而老年代中因为对象的存活率较高、周期长,就用“标记-整理”或“标记-清除”算法来回收。 

3. 内存分配 

1)对象优先在Edn分配,大多数情况下,对象在新生代Edn区中分配。当Edn区没有足够的空间时,虚拟机会发动一次新生代DC。 
2)大对象直接进入老年代,如很长的字符串及数组。 
3)长期存活的对象将进入老年代。如果对象在Edn出生并经过一次新生代GC后任然存活,并能被Survivor容纳的话,将被移到Suivivor中,并将对象年龄设为1.对象在Survivor中没经过一次新生代GC,年龄加1,当年龄到一定程度(默认是15),就会被放到老年代中。 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值