Java GC Roots

  • Java中的GCRoot
  • 虚拟机栈中引用的对象
  • 方法区类的静态成员引用的对象
  • 方法区常量引用的对象
  • 本地方法栈中JNI引用的对象


Java中的GCRoot

哪些对象可作为GCRoots对象呢? 包括如下:

  • 虚拟机栈帧上本地变量表中的引用对象(方法参数、局部变量、临时变量)
  • 方法区中的静态属性引用类型对象、常量引用对象
  • 本地方法栈中的引用对象(Native方法的引用对象)
  • Java虚拟机内部的引用对象,如异常对象、系统类加载器等
  • 所以被同步锁(synchronize)持有的对象
  • Java虚拟机内部情况的注册回调、本地缓存等

虚拟机栈中引用的对象

a是栈帧中的本地变量,a就是GC Root,由于a=null,a与new Test()对象断开了链接,所以对象会被回收。

public class Test{
    public static void main(String[] args) {
	     Testa = new Test();
	     a = null;
    }
}



方法区类的静态成员引用的对象

情况一:栈帧中的本地变量a =null,由于a断开了与GC Root对象(a对象)的联系,所以a对象会被回收。

情况二:Test的成员变量r赋值了变量的引用,并且r成员变量是静态的,所以r就是一个GC Root对象,所以r指向的对象不会被回收。

public class Test{
    public static Test = r;
    public static void main(String[] args){
       Test a = new Test();
       a.r = new Test();
       a = null;
    }
}



方法区常量引用的对象

常量r引用的对象不会因为a引用的对象的回收而被回收。

public class Test{
    public static final Test r = new Test();
    public static void main(String[] args){
       Test a = new Test();
       a = null;
    }
}



本地方法栈中JNI引用的对象

本地方法就是一个 java 调用非 java 代码的接口,该方法并非 Java 实现的,可能由 C 或 Python等其他语言实现的。
Java 通过 JNI 来调用本地方法, 而本地方法是以库文件的形式存放的(在 WINDOWS 平台上是 DLL 文件形式,在 UNIX 机器上是 SO 文件形式)。通过调用本地的库文件的内部方法,使 JAVA 可以实现和本地机器的紧密联系,调用系统级的各接口方法。

当调用 Java 方法时,虚拟机会创建一个栈桢并压入 Java 栈,而当它调用的是本地方法时,虚拟机会保持 Java 栈不变,不会在 Java 栈祯中压入新的祯,虚拟机只是简单地动态连接并直接调用指定的本地方法

JNIEXPORT void JNICALL Java_com_pecuyu_jnirefdemo_MainActivity_newStringNative(JNIEnv *env, jobject instance,jstring jmsg) {
...
   // 缓存String的class
   jclass jc = (*env)->FindClass(env, STRING_PATH);
}

java 以root权限生成文件 java root对象_java 以root权限生成文件