• Java垃圾回收机制


    原文地址http://www.cnblogs.com/dolphin0520/p/3783345.html

    一.如何确定某个对象是“垃圾”?

      在这一小节我们先了解一个最基本的问题:如果确定某个对象是“垃圾”?既然垃圾收集器的任务是回收垃圾对象所占的空间供新的对象使用,那么垃圾收集器如何确定某个对象是“垃圾”?—即通过什么方法判断一个对象可以被回收了。

      在java中是通过引用来和对象进行关联的,也就是说如果要操作对象,必须通过引用来进行。那么很显然一个简单的办法就是通过引用计数来判断一个对象是否可以被回收。不失一般性,如果一个对象没有任何引用与之关联,则说明该对象基本不太可能在其他地方被使用到,那么这个对象就成为可被回收的对象了。这种方式成为引用计数法。

      这种方式的特点是实现简单,而且效率较高,但是它无法解决循环引用的问题,因此在Java中并没有采用这种方式(Python采用的是引用计数法)。看下面这段代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public class Main {
        public static void main(String[] args) {
            MyObject object1 = new MyObject();
            MyObject object2 = new MyObject();
             
            object1.object = object2;
            object2.object = object1;
             
            object1 = null;
            object2 = null;
        }
    }
     
    class MyObject{
        public Object object = null;
    }

      最后面两句将object1和object2赋值为null,也就是说object1和object2指向的对象已经不可能再被访问,但是由于它们互相引用对方,导致它们的引用计数都不为0,那么垃圾收集器就永远不会回收它们。

      为了解决这个问题,在Java中采取了 可达性分析法。该方法的基本思想是通过一系列的“GC Roots”对象作为起点进行搜索,如果在“GC Roots”和一个对象之间没有可达路径,则称该对象是不可达的,不过要注意的是被判定为不可达的对象不一定就会成为可回收对象。被判定为不可达的对象要成为可回收对象必须至少经历两次标记过程,如果在这两次标记过程中仍然没有逃脱成为可回收对象的可能性,则基本上就真的成为可回收对象了。

      至于可达性分析法具体是如何操作的我暂时也没有看得很明白,如果有哪位朋友比较清楚的话请不吝指教。

      下面来看个例子:

    1
    2
    3
    4
    5
    6
    7
    Object aobj = new Object ( ) ;
    Object bobj = new Object ( ) ;
    Object cobj = new Object ( ) ;
    aobj = bobj;
    aobj = cobj;
    cobj = null;
    aobj = null;

       第几行有可能会使得某个对象成为可回收对象?第7行的代码会导致有对象会成为可回收对象。至于为什么留给读者自己思考。

      再看一个例子:

    1
    2
    3
    String str = new String("hello");
    SoftReference<String> sr = new SoftReference<String>(new String("java"));
    WeakReference<String> wr = new WeakReference<String>(new String("world"));

      这三句哪句会使得String对象成为可回收对象?第2句和第3句,第2句在内存不足的情况下会将String对象判定为可回收对象,第3句无论什么情况下String对象都会被判定为可回收对象。

      最后总结一下平常遇到的比较常见的将对象判定为可回收对象的情况:

      1)显示地将某个引用赋值为null或者将已经指向某个对象的引用指向新的对象,比如下面的代码:

    1
    2
    3
    4
    5
    Object obj = new Object();
    obj = null;
    Object obj1 = new Object();
    Object obj2 = new Object();
    obj1 = obj2;

        2)局部引用所指向的对象,比如下面这段代码:

    1
    2
    3
    4
    5
    6
    7
    8
    void fun() {
     
    .....
        for(int i=0;i<10;i++) {
            Object obj = new Object();
            System.out.println(obj.getClass());
        }   
    }

       循环每执行完一次,生成的Object对象都会成为可回收的对象。

      3)只有弱引用与其关联的对象,比如:

    1
    WeakReference<String> wr = new WeakReference<String>(new String("world"));
  • 相关阅读:
    brewhome
    WIN7下安装SQL server 2008 R2“出现性能计数器注册表配置单元一致性”失败的解决办法(新)
    话说ELK使用安装,结合.NET Core、ABP框架Nlog日志
    支付系统架构
    高可用Redis服务架构分析与搭建
    基于STS和JWT的微服务身份认证
    全面解读NoSQL数据库Redis的核心技术与应用实践
    Redis应用及安装
    微服务实践分享与探讨
    Docker的核心概念,镜像操作
  • 原文地址:https://www.cnblogs.com/111testing/p/8169689.html
Copyright © 2020-2023  润新知