Java 的垃圾回收如何判断哪个对象可以被回收

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 的垃圾回收如何判断哪个对象可以被回收相关的知识,希望对你有一定的参考价值。

Java 的垃圾回收

java对象符合以下条件便会被垃圾回收:

1.所有实例都没有活动线程访问。
2.没有被其他任何实例访问的循环引用实例。 
3.Java 中有不同的引用类型。判断实例是否符合垃圾收集的条件都依赖于它的引用类型。

       

在编译过程中作为一种优化技术,Java 编译器能选择给实例赋 null 值,从而标记实例为可回收。

class Animal 

public static void main(String[] args) 

Animal lion = new Animal();

System.out.println("Main is completed.");



protected void finalize() 

System.out.println("Rest in Peace!");



参考技术A 有一种内部机制是一个链表保存一个对象引用的所有对象,当一个对象不在任何一个链表中时,认为该对象不可达,即没有被任何对象引用,可以被垃圾回收。好象还用到了图论的知识,细节不记得了。 参考技术B 垃圾回收器会在一定的时间内自动运行,判断对象是否被回收很重要的一点是该对象是否被引用句柄所持有! 参考技术C 这涉及到堆和栈的问题。栈空间中的变量引用指向堆空间中的对象,一旦堆空间中的某个对象没有哪个引用指向它,jvm就认为这个对象已经没用了,开始垃圾回收 参考技术D java是自动对那些不用的对象进行回收
也可以指定对象使其失效来告知垃圾回收器回收这个对象
如:String string = "hanxiucao";
string = null;
这样垃圾回收器就知道了要回收string对象
但是
垃圾回收器否真的回收string对象不一定
交个好友啊:934765410

参考资料:《SCJP试题精解》 http://blog.163.com/java_communication/blog/static/1640625262010529481420/

垃圾回收算法

如何确定对象是否为垃圾?

Java中采用引用计数法和可达性分析来确定对象是否应该被回收。

  • 1.引用计数法

在Java中如果要操作对象,就必须获取该对象的引用,所以可以通过引用计数法来判断该对象是否可以被回收。在给该对象添加一个引用时,引用计数加1;在为该对象减少一个引用时,引用计数减1;如果一个对象的引用计数为0,则表示该对象此时没有被引用,可以被回收。
注意:引用计数法容易产生循环引用(指两个对象相互引用,导致引用一直存在而不能被回收)的问题


Object1              Object2
     |                          |
    v                          v
Reference <-----> Reference

  • 2.可达性分析法

可达性分析法可以解决引用计数法的循环引用问题。
具体做法:
        首先定义一些GC Roots对象,然后以这些对象作为起点向下搜索,如果在GC Roots和一个对象之间没有可达路径,则称该对象是不可达的。不可达对象至少要经过两次标记才能判定其是否可以被回收。如果在两次标记后该对象仍然是不可达的,则将被垃圾收集器回收。

Java中常用的垃圾回收算法

Java中常用的垃圾回收算法有标记清、复制、标记整理和分代收集算法。

1.标记清除算法

标记清除算法是最基础的垃圾回收算法,其过程分为标记和清除两个阶段。在标记阶段标记所有需要回收的对象,在清除阶段清除可回收的对象并释放其内存空间。
注意:过程如图所示,由于标记清楚算法在清理对象所占用的内存空间后并没有重新整理可用的内存空间,因此如果内存中回收的小对象过多,则会引起内存碎片化的问题,进而引起大对象无法获得连续可用内存空间的问题。

2.复制算法

复制算法是为了解决标记清除算法内存碎片化的问题而设计的。复制算法首先将内存划分为两块大小相等的内存区域,新生成的对象都被存放到区域1中,在区域1内的对象存储满后会对区域1进行一次标记,并把标记后仍然存活的对象全部复制到区域2中,这时区域1将不存在任何存活的对象,直接清理整个区域1内的内存即可。
优缺点:复制算法的内存清理效率高且易于实现,但是可用的内存空间被压缩到原来的一半,因此存在大量的内存浪费。同时,在系统中有许多的大量长时间存活的对象,这些对象在两个区域之间来回复制会影响系统的运行效率。

3.标记整理算法

标记整理算法结合了标记清楚算法和复制算法的优点。其标记阶段和标记清除算法的标记阶段相同,在标记完成后将存活的对象移动到内存的另一端,然后清除该端的对象并释放内存

4.分代收集算法

无论是标记清楚算法、复制算法还是标记整理算法,都无法对所有类型(长、短生命周期、大、小对象)的对象进行垃圾回收。因此针对不同对象类型,JVM采用了不同的垃圾回收算法,该算法被称为分代收集算法。

分代收集算法是根据对象的不同类型将内存划分成不同的区域,JVM将堆划分为新生代和老年代。

  • 新生代主要存放新生成的对象(特点是生命周期短),每次进行垃圾回收时都有大量的对象被回收。
  • 老年代主要存放大对象和生命周期长的对象,可回收的垃圾相对较少。

因此JVM根据不同类型的对象的特点进行选择不同的算法。

  • 新生代大部分采用复制算法。因为新生代每次进行垃圾回收的时候都有大量的对象 被回收,需要复制的对象少,不存在大量对象来回复制的问题。
  • 老年代主要存放的是生命周期较长的对象和大对象,因此每次有少量非存活的对象需要被回收,所以使用标记清除算法

以上是关于Java 的垃圾回收如何判断哪个对象可以被回收的主要内容,如果未能解决你的问题,请参考以下文章

垃圾回收算法

垃圾回收算法

垃圾回收算法

Java 垃圾回收

Java垃圾回收-GC

Java开发中啥是垃圾回收?