程序计数器

JVM中的计数器

在堆里面存放着Java世界中几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还“存活”着,哪些已经“死去”(“死去”即不可能再被任何途径使用的对象)了。

根据什么判断对象是否可以被GC掉呢

                                                                         

1.引用计数算法

在网上讲述大多判断对象是否还存活的方法为: 在对象中添加一个引用计数器,引用+1。引用失效则-1。任何时刻计数器为0的对象便不能被使用了

 

                                  

 

 

当然引用计数算法在使用上面,判断效率还是很高的。总之是个不错的算法。比如微软的COM技术、使用ActionScript 3的FlashPlayer、Python语言以及在游戏脚本领域得到许多应用的Squirrel中都使用

了引用计数算法进行内存管理。 但是!在JAVA之中却没有使用引用技术算法来进行管理内存。因为这个算法在许多情况下出现的问题需要进行考虑,比如两个对对象之间的循环引用!

 
     
/**
 * @Author: Liy
 * @Date: 2020/5/20 10:17
 * @Description: 引用计数算法回收引用
 **/
public class ReferenceCountingGC {
​
    public Object instance = null;
​
    private static final int _1MB = 1024 * 1024;
​
    /**
     * jie个成员变量用来占点内存
     */
    private byte[] bigSize = new byte[2 * _1MB];
​
    public static void testGC() {
        ReferenceCountingGC objA = new ReferenceCountingGC();
        ReferenceCountingGC objB = new ReferenceCountingGC();
        objA.instance = objB;
        objB.instance = objA;
​
        objA = null;
        objB = null;
​
        // 此处会发生GC,引用计数算法是否能回收objA And objB
        System.gc();
    }
​
    public static void main(String[] args) {
        testGC();
    }
}
​


此处的运行结果日志中便会 出现,“4603K->210K”。虽然两个对象之间在互相引用,但是JVM并没有放弃回收它们。从而可想JVM并不是通过引用技术算法来回收对象的

 

2.可达性分析算法

JAVA、C#便是通过可达性算法来判断对象是否还存活的。通过一系列称为“GC Roots”的根对象作为起始节点集,从这些节点开始,根据引用关系向下进行搜索,搜索过程所走过的路径称为“引用链”,如

果某个对象到GCRoots间没有任何引用链相连,或者用图论的话来说就是从GC Roots到这个对象不可达时,则证明此对象是不可能再被使用的。

 

上图:

 

                      

 

在Java技术体系里面,固定可作为GC Roots的对象包括以下几种:

1.在虚拟机栈(栈帧中的本地变量表)中引用的对象,譬如各个线程被调用的方法堆栈中使用到的参数、局部变量、临时变量等

2.·在方法区中类静态属性引用的对象,譬如Java类的引用类型静态变量

3.·在方法区中常量引用的对象,譬如字符串常量池(String Table)里的引用

4.·在本地方法栈中JNI(即通常所说的Native方法)引用的对象

5.·Java虚拟机内部的引用,如基本数据类型对应的Class对象,一些常驻的异常对象(比如NullPointExcepiton、OutOfMemoryError)等,还有系统类加载器

6.·所有被同步锁(synchronized关键字)持有的对象

7.·反映Java虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等

 

 

无论我们是用引用还是可达性,判断对象是否还存活都和“引用”有关系

 

 

原文地址:https://www.cnblogs.com/prock-Liy/p/13229272.html