zoukankan      html  css  js  c++  java
  • JVM之GC Roots

      Java堆用于储存对象实例,我们只要不断地创建对象,并且保证GC Roots到对象之间有可达路径 来避免垃圾回收机制清除这些对象,那么随着对象数量的增加,总容量触及最大堆的容量限制后就会 产生内存溢出异常。

    -------------------------------------------------------------------

      这里还是第二章的内容。之前早早把第二章的笔记放上去,有点草率了。这里要解释一下什么叫做GC Roots,什么叫做可达。

      首先引入一个问题:怎么判断一个对象是可以被回收的?

      我们知道Java对象实例都是被Java栈中的引用所操作的,如果说不再有引用对这个对象进行操作,那么就可以认为这个对象可以被回收了。怎么实现这个目标呢?一个简单的办法就是给对象添加一个引用计数器,有一个引用将使用这个对象时就加1,而每当一个引用失效时就减1。如此,任意时刻,这个引用计数器的值为0时,这个对象就被称为垃圾,那么垃圾回收器就可以对它进行回收操作。

      但是这个引用计数法,每有一个对象就需要维护一个引用计数器,且这个计数器本身也是有开销的;另外,还有循环引用的问题,看下面的代码及注释:

    public class Test {
        public static void main(String[] args) {
            new Test().testCountUseless();
            //已经离开了两个对象的作用域,计数器都减1,但两者计数器不为0,无法被回收
            //。。。其它代码
        }
    
        public void testCountUseless() {
            Parent parent = new Parent();//初始化,引用计数器为1
            Son son = new Son();//初始化,引用计数器为1
            parent.setSon(son);//son被引用,son计数器加到2
            son.setParent(parent);//parent被引用,parent计数器加到2
            System.out.println("test");
        }
    }

      所以,JVM一般都不采用引用计数法进行对象是否可以回收的判断。它采用GC Roots或者叫Tracing Roots的做法,用一组活跃的引用作为根集合作为引子,从每一个根向下搜索,如果某个对象与这些根集合没有任何引用链相连时,那么这个对象就被当做不可用。

      JVM一般采用哪些引用作为GC Roots引用呢?(除了Java Heap里的对象,其它的如栈,方法区里的对象基本都可以作为GC Roots)

    1.   Class - 由系统类加载器(system class loader)加载的对象,这些类是不能够被回收的,他们可以以静态字段的方式保存持有其它对象。我们需要注意的一点就是,通过用户自定义的类加载器加载的类,除非相应的Java.lang.Class实例以其它的某种(或多种)方式成为roots,否则它们并不是roots,.
    2.   Thread - 活着的线程
    3.   Stack Local - Java方法的local变量或参数
    4.   JNI Local - JNI方法的local变量或参数
    5.   JNI Global - 全局JNI引用
    6.   Monitor Used - 用于同步的监控对象
    7.   Held by JVM - 用于JVM特殊目的由GC保留的对象,但实际上这个与JVM的实现是有关的。可能已知的一些类型是:系统类加载器、一些JVM知道的重要的异常类、一些用于处理异常的预分配对象以及一些自定义的类加载器等。然而,JVM并没有为这些对象提供其它的信息,因此需要去确定哪些是属于"JVM持有"的了。

    -------------------------------------------------------------------

    参考

    • https://www.yourkit.com/docs/java/help/gc_roots.jsp
    • https://blog.csdn.net/weixin_41910694/article/details/90706652

  • 相关阅读:
    Spring配置文件中使用ref local与ref bean的区别
    基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务
    Spring事务配置的五种方式
    [codeforces-543B]bfs求最短路
    [hdu5218]DP-约瑟夫环变形
    [hdu5215]无向图找奇偶环
    [hdu5216]排序
    [zoj3591]Nim 游戏
    [zoj3596]DP(BFS)
    [zoj3593]扩展欧几里得+三分
  • 原文地址:https://www.cnblogs.com/bruceChan0018/p/15063824.html
Copyright © 2011-2022 走看看