文档章节

java 垃圾回收机制

呆萌的我
 呆萌的我
发布于 2015/10/18 15:44
字数 953
阅读 21
收藏 0
很多书中提到,判断一个对象是否应该存活,是使用程序计数器的,对象有一个引用计数器,每当一个地方引用,计数器就加1,引用失效,计数器减1,当计数为0,该对象可以被回收。

引用计数器算法的实现简单,判定效率也很高,但是,java虚拟机里面没有选用计数器算法来管理内存,主要原因是它很难解决对象之间的循环引用问题。
public class TestGC {

    public Object obj = null;    public static void main(String[] args) {
        TestGC gc1 = new TestGC();
        TestGC gc2 = new TestGC();

        gc1.obj = gc2;
        gc2.obj = gc1;

        gc1 = null;
        gc2 = null;

        System.gc();
    }

}

对象gc1、gc2已经被gc回收,如果采用计数器算法,将造成内存泄漏。

可达性分析算法

    基本思想是通过一系列的“GC Roots”对象作为起点,向下搜索,搜索所经过的路径称为引用链,当一个对象到GC Roots没有任何引用引用链,此对象可以被回收.

jdk1.2之后,java对引用的概念进行了扩充,将分为强引用、软引用、弱引用、虚饮用四种:

  • 强引用类似于Object obj = new Object();强引用还存在,垃圾收集器永远不会回收被引用对象。

  • 引用描述一些还在用,但并非必须的对象。对于软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象列入回收范围之中进行第二次回收。如果回收后还没有足够内存,抛出异常。

  • 弱引用描述非必要对象,比弱引用更弱一些,被引用关联的对象只能生存在下一次垃圾收集发生之前。当垃圾收集器工作时,无论当前内存是否足够,都会回收掉被弱引用关联的对象。

  • 虚引用:一个对象是否存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的主要目的就是能在这个对象被收集器回收时收到一个系统通知。

    要宣布一个对象的死亡,需要经历两个过程:

    如果对象在进行可达性分析后发现没有与GC Roots相连接的引用链,那它将会被第一次标记并且进行一次筛选,筛选条件是此对象是否有必要执行finalize()方法。当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,虚拟机将两种情况都视为“没有必要执行”。

    如果这个对象被判定为有必要执行finalize()方法,那么这个对象将会放置在一个F-Queue的队列中,并稍后由一个虚拟机自动建立,低优先级的Finalizer线程去执行它。但并不是立即执行,因为如果finalize()方法执行缓慢或者死循环,可能导致整个内存回收系统崩溃。如果在finalize()中将this赋值一个变量,第二次标记时将会被移除“即将回收”的集合。

public class FinalEscapeGC {

    public static FinalEscapeGC SAVE_HOOK = null;
    public  void isAlive() {
        System.out.println("FinalEscapeGC.isAlive()");
    }
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("FinalEscapeGC.finalize()");
        FinalEscapeGC.SAVE_HOOK = this;
    }
    public static void main(String[] args) throws InterruptedException {

        SAVE_HOOK = new FinalEscapeGC();        //对象第一次成功自救
        SAVE_HOOK = null;
        System.gc();

        Thread.sleep(500);
        if(SAVE_HOOK != null) {
            SAVE_HOOK.isAlive();
        }   else {
            System.out.println("is deed");
        }        //由于finalize只会被执行一次,所以自救失败
        SAVE_HOOK = null;
        System.gc();
        
        Thread.sleep(500);
        if(SAVE_HOOK != null) {
            SAVE_HOOK.isAlive();
        }   else {
            System.out.println("is deed");
        }
    }

}


© 著作权归作者所有

共有 人打赏支持
呆萌的我
粉丝 4
博文 15
码字总数 15443
作品 0
天津
私信 提问
Java内存垃圾回收(Garbage Collection)机制基本方法和原则:System.gc()与finalize()

版权声明:本文为Zhang Phil原创文章,请不要转载! https://blog.csdn.net/zhangphil/article/details/84650786 Java内存垃圾回收(Garbage Collection)机制基本方法和原则:System.gc()与f...

zhangphil
2018/12/01
0
0
JVM系列第8讲:JVM 垃圾回收机制

在第 6 讲中我们说到 Java 虚拟机的内存结构,提到了这部分的规范其实是由《Java 虚拟机规范》指定的,每个 Java 虚拟机可能都有不同的实现。其实涉及到 Java 虚拟机的内存,就不得不谈到 Ja...

陈树义
2018/11/21
0
0
My java——JVM(垃圾回收)四

续My java——JVM(内存域) 中讲述了Java在JVM中的内存使用,其实在我们出来java程序时基本上有两个地方的内存处理 一是栈、二是堆,JVM会自动回收堆中的内存,也就我们所说的垃圾回收,那J...

tngou
2013/03/20
0
0
Java finalize方法

《JAVA编程思想》: java提供finalize()方法,垃圾回收器准备释放内存的时候,会先调用finalize()。 (1).对象不一定会被回收。 (2).垃圾回收不是析构函数。 (3).垃圾回收只与内存有关。 (4)....

清风伴月
2017/10/22
0
0
Java的垃圾回收之算法[转]

引言 Java的堆是一个运行时数据区,类的实例(对象)从中分配空间。Java虚拟机(JVM)的堆中储存着正在运行的应用程序所建立的所有对象,这些对象通过new、newarray、anewarray和multianewarray等...

kext
2012/03/20
0
0

没有更多内容

加载失败,请刷新页面

加载更多

vue 对对象的属性进行修改时,不能渲染页面 vue.$set()

我在vue里的方法里给一个对象添加某个属性时,我console.log出来的是已经更改的object ,但是页面始终没有变化 原因如下: **受现代 JavaScript 的限制 (而且 Object.observe 也已经被废弃),...

Js_Mei
今天
2
0
开始看《Java学习笔记》

虽然书买了很久,但一直没看。这其中也写过一些Java程序,但都是基于IDE的帮助和对C#的理解来写的,感觉不踏实。 林信良的书写得蛮好的,能够帮助打好基础,看得出作者是比较用心的。 第1章概...

max佩恩
昨天
12
0
Redux 三大原则

1.单一数据源 在传统的MVC架构中,我们可以根据需要创建无数个Model,而Model之间可以互相监听、触发事件甚至循环或嵌套触发事件,这些在Redux中都是不被允许的。 因为在Redux的思想里,一个...

wenxingjun
昨天
8
0
跟我学Spring Cloud(Finchley版)-12-微服务容错三板斧

至此,我们已实现服务发现、负载均衡,同时,使用Feign也实现了良好的远程调用——我们的代码是可读、可维护的。理论上,我们现在已经能构建一个不错的分布式应用了,但微服务之间是通过网络...

周立_ITMuch
昨天
5
0
XML

学习目标  能够说出XML的作用  能够编写XML文档声明  能够编写符合语法的XML  能够通过DTD约束编写XML文档  能够通过Schema约束编写XML文档  能够通过Dom4j解析XML文档 第1章 xm...

stars永恒
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部