JVM(四)垃圾回收与算法

一、简介 

 

 

 

二、如何确定垃圾

 

2.1 引用计数法

在java中,引用和对象是关联的。如果要操作对象则必须用引用进行。因此,一个简单的办法是通过引用计数来判断一个对象是否可以回收。在对象头中分配一个空间来保存该对象被引用的次数,如果该对象被引用了,则加1,如果该引用被取消了,则减1,当该对象的引用为0时,就被当成垃圾回收了。

垃圾收集的开销被分摊到整个应用程序的运行当中;当某个对象的引用减为0时,需要递归遍历它所指向的所有域,将它所有域所指向的对象的引用计数都减1,然后才回收当前对象,若指向的对象减1之后也变成0了,也将被一起回收。

 

该方法有一个循环引用问题,会导致内存泄露。

比如:

public class GcDemo {

    public static void main(String[] args) {
        //分为6个步骤
        GcObject obj1 = new GcObject(); //Step 1
        GcObject obj2 = new GcObject(); //Step 2

        obj1.instance = obj2; //Step 3
        obj2.instance = obj1; //Step 4

        obj1 = null; //Step 5
        obj2 = null; //Step 6
    }
}

class GcObject{
    public Object instance = null;
}

它们的互相引用如图所示:

如图,执行到step4时可以明显的看出两个对象都被引用了两次,引用计数都为2。

 

而执行step5和step6后如图所示:

Step5:栈帧中obj1不再指向Java堆,GcObject实例1的引用计数减1,结果为1;

Step6:栈帧中obj2不再指向Java堆,GcObject实例2的引用计数减1,结果为1。

 

两者都不为0,因此不会被当成垃圾回收,便产生了内存泄露问题。

 

 

2.2可达性分析法

目前主流的虚拟机都是采用GC Roots Tracing算法。该算法的核心是从GC Roots对象作为起始点,如果一个对象和GC Roots对象之间没有可达路径,则称该对象不可达

如图,可以作为GC Roots的对象如下:

  • 虚拟机栈的栈帧的局部变量表所引用的对象;
  • 本地方法栈的JNI所引用的对象;
  • 方法区的静态变量和常量所引用的对象;

可以看到实例3和5之间虽然连通,但是没有一个跟GC Roots关联,是不可达的。

不可达对象变成可回收对象至少要经过两次标记过程,两次标记后将面临回收

 

 

finalize()方法是对象脱逃死亡命运的最后一次机会。

 

 

三、垃圾回收算法

 

3.1标记清除算法(Mark-Sweep)

最基础的垃圾回收算法,分为两个阶段,标记和清除。标记阶段标记出所有需要回收的对象,清除阶段回收被标记的对象所占用的空间。如图:

 

从图中我们可以发现,该算法最大的问题是内存碎片化严重,后续可能发生大对象不能找到可利用空间的问题。

 

 

3.2复制算法(copying)

为了解决Mark-Sweep算法内存碎片化的缺陷而被提出的算法。按内存容量将内存划分为等大小的两块。每次只使用其中一块,当这一块内存满后将尚存活的对象复制到另一块上去,把已使用的内存清掉,如图:

这种算法虽然实现简单,内存效率高,不易产生碎片;但是最大的问题是可用内存被压缩到了原本的一半,且存活对象增多的话,Copying算法的效率会大大降低。

 

 

3.3标记整理算法(Mark-Compact)

结合了以上两个算法,为了避免缺陷而提出。标记阶段和Mark-Sweep算法相同,标记后不是清理对象,而是将存活的对象移动向内存的一端,然后清理端边界外的对象。如图:

该算法的缺点是效率低。

 

 

 

参考

https://www.zhihu.com/question/21539353@Gityuan的回答

https://blog.csdn.net/luzhensmart/article/details/81431212

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值