java垃圾回收机制

前言

  • 垃圾收集GC(Garbage Collection)是Java语言的核心技术之一,GC通过确定对象是否被活动对象引用来确定是否收集该对象。GC首先要判断该对象是否是可以收集。两种常用的方法是引用计数算法和对象引用遍历。
  • 垃圾回收机制主要作用于java堆(Heap),也就是jvm用于存放对象实例的地方.

引用计数算法

引用计数是垃圾收集器中的早期策略。在这种方法中,堆中每个对象(不是引用)都有一个引用计数。当一个对象被创建时,且将该对象分配给一个变量,该变量计数设置为1。当任何其它变量被赋值为这个对象的引用时,计数加1(a = b,则b引用的对象+1),但当一个对象的某个引用超过了生命周期或者被设置为一个新值时,对象的引用计数减1。任何引用计数为0的对象可以被当作垃圾收集。当一个对象被垃圾收集时,它引用的任何对象计数减1。

  1. 优点:引用计数收集器可以很快的执行,交织在程序运行中。对程序不被长时间打断的实时环境比较有利。
  2. 缺点: 无法检测出循环引用。如父对象有一个对子对象的引用,子对象反过来引用父对象。这样,他们的引用计数永远不可能为0.如:
public class ReferenceCountingGC{
    public Object instance = null;
    public static void testGC(){
        ReferenceCountingGC objA = new ReferenceCountingGC ();
        ReferenceCountingGC objB = new ReferenceCountingGC ();
        objB.instance = objA;
        objA.instance = objB;
        objA = null;
        objB = null;
        System.gc();
    }
}

要是虚拟机用了引用计数算法,那么上面的objA和objB会不会回收呢?

可达性分析算法(Rearchability Analysis)

早期的JVM使用引用计数,现在在主流的商用的程序语言中,都是称通过可达性分析算法来判断对象是否还存活着。这个算法是通过一系列的“GC roots”的对象作为起点,从这些节点向下搜索,搜索所经过的路径称为引用链,当一个对象到GC roots没有任何引用链相连的时候。则此对象是不可用的。不可用的对象则是JVM判定为可回收的对象。
在java中,可作为gc roots的对象包括下面几种:

  • 虚拟机栈中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI引用的对象

就算是在可达性分析算法是不可达的对象,也不是非死不可,现在它们只是被“怀疑”,要真正宣告一个对象死亡,至少要经过两个阶段:在可达性分析的时候,要是不可达,那么它会被第一次标记并且进行一次筛选,筛选的条件是此对象有没有必要执行finalize()方法,当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过。那么,此对象就没有必要执行finalize()方法。
当一个对象被判定为有必要执行finalize()方法的时候,它就会被放到一个F-Queue的队列中,并且稍后会有一个由虚拟机自动创建的线程来执行它,而且在执行它的时候,虚拟机不保证会等待它运行结束,这是因为要是finalize()里面有死循环或者什么的就麻烦了,就会堵塞队列,有时会导致垃圾回收系统崩溃。稍后GC还会再次对F-Queue进行小规模地第二次标记,如果这次不幸成功被标记,那么它基本上真的就会被回收了。上面说了,finalize()不保证被完全执行,所以我们在开发中,最好不要用它来关闭资源什么的,因为try finally能更好地完成这项工作,所以建议大家忘记这个方法。

参考资料

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 1. 垃圾回收的意义在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对象;而在...
    爱情小傻蛋阅读 1,039评论 0 11
  • 一、垃圾回收机制的意义Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃...
    任任任任师艳阅读 774评论 0 0
  • 程序计数器、虚拟机栈、本地方法栈三个内存区域随线程而生,随线程而灭,一般不需要考虑内存回收的问题。但是Java堆和...
    云飞扬1阅读 1,204评论 0 49
  • 来自: Android梦想特工队作者: Aaron主页: http://www.wxtlife.com/原...
    技术特工队阅读 4,648评论 0 28
  • 这是开始的时候, 也是结束的时候, 一场雨把燥热的天气, 淋了又淋。 只剩下, 只剩下风儿在一旁看书……
    小剧在成长阅读 160评论 0 4

友情链接更多精彩内容