GC 如何找到 GC 根和其他对象引用
How GC finds GC roots and other object references
根据这篇文章How Garbage Collection Works有四种Gc根:
- Local variables are kept alive by the stack of a thread. This is not a real object virtual reference and thus is not visible. For
all intents and purposes, local variables are GC roots.
- Active Java threads are always considered live objects and are therefore GC roots. This is especially important for thread local
variables.
- Static variables are referenced by their classes. This fact makes them de facto GC roots. Classes themselves can be garbage-collected, which would remove all referenced static variables. This is of special importance when we use application servers, OSGi containers or class loaders in general. We will discuss the related problems in the Problem Patterns section.
- JNI References are Java objects that the native code has created as part of a JNI call. Objects thus created are treated specially because the JVM does not know if it is being referenced by the native code or not. Such objects represent a very special form of GC root, which we will examine in more detail in the Problem Patterns section below.
在 JVM 规范中,堆栈帧中的局部变量没有类型,它只是一个字节数组,编译器负责为这些局部变量生成特定类型的指令,例如 iload、fload、aload 等. 很明显,GC 无法仅通过查看堆栈帧的局部变量部分来找到对对象的引用。
我的问题是:
GC 是如何找到这些根的?
GC 如何在堆栈中找到引用的局部变量
object 而不是其他类型的变量(例如 iconst 存储的变量)?
然后 Gc 如何找到那些对象的字段来创建一个可访问的
树?
是否使用JVM自己定义的指令来查找那些
对象?
最后这句话在文章中是什么意思?
This is not a real object virtual reference and thus is not visible
- How GC finds those roots at all?
JVM 提供内部 (C / C++) API 用于查找根。 JVM 知道 Java 堆栈帧在哪里,每个 Java 的静态帧 class 在哪里,实时 JNI object 句柄在哪里,等等。 (它知道,因为它参与创建它们,并跟踪它们。)
- How GC can find local variables in the stack that are references to object and are not other type of variables.
JVM 为每个方法保留信息,说明每个堆栈帧中的哪些单元格是引用变量。 GC可以找出每个堆栈帧对应的方法......就像fillInStackTrace
一样。
(for instance constant)
这实际上并不相关。常量(即 final
字段)没有得到特殊处理。
- Then how GC finds fields of those objects to create an accessible tree?
JVM 为每个 class 保留信息以说明哪些静态字段和实例字段是引用变量。每个 object 的 header 中都有一个字段引用 class.
整个过程称为“标记”,在您查看的页面中有描述。
- Does it use instruction that are defined by jvm itself to find those objects?
我不确定你在问什么。但“可能是”。 GC 是 JVM 的一个组件,所以所做的一切都是“由 JVM 定义的”。
- And lastly what is the meaning of this sentence in the article?
This is not a real object virtual reference and thus is not visible
可能是说线程的堆栈不是 Java object ... 这是真的。但我认为您需要询问该电子书的作者;他们的名字见 https://www.dynatrace.com/resources/ebooks/javabook/ 的底部。
你添加了这个:
In JVM specification local variables in the frames of stack have no type and it's just somehow an array of bytes and it's the responsibility of compiler to generate type specific instruction for those local variables for instance iload, fload, aload, etc. So clearly GC can not find references to object by only looking at local variable section of the stack frames.
事实上,事实并非如此。正如@Holder 提醒我的那样,验证者 通过模拟初始化它们的字节码的效果来推断 堆栈帧中单元格的类型。此外,class 文件中的每个方法都有一个 StackMapTable
属性,其中包含用于协助(并加快)验证程序类型确定的信息。
稍后,GC可以从JVM获取推断的类型信息。
(理论上 GC 还可以利用 StackMapTable
信息来确定局部变量何时超出范围...在一种方法。但显然它不在 HotSpot JVM 中;参见 Does the StackMapTable affect the garbage collection behavior?)
该电子书中对垃圾 collection 的描述(故意)简短而高级。但你会发现大多数描述都是如此。深层细节复杂。
如果您真的想(并且需要)了解 GC 的工作原理,我的建议是:
- 要了解当前 Java 实现的工作原理 阅读 OpenJDK 源代码。
- 追踪并阅读 Sun 和 Oracle 关于 Java GC 的研究论文。
- 找一本关于垃圾的好教科书Collection。
根据这篇文章How Garbage Collection Works有四种Gc根:
- Local variables are kept alive by the stack of a thread. This is not a real object virtual reference and thus is not visible. For all intents and purposes, local variables are GC roots.
- Active Java threads are always considered live objects and are therefore GC roots. This is especially important for thread local
variables.- Static variables are referenced by their classes. This fact makes them de facto GC roots. Classes themselves can be garbage-collected, which would remove all referenced static variables. This is of special importance when we use application servers, OSGi containers or class loaders in general. We will discuss the related problems in the Problem Patterns section.
- JNI References are Java objects that the native code has created as part of a JNI call. Objects thus created are treated specially because the JVM does not know if it is being referenced by the native code or not. Such objects represent a very special form of GC root, which we will examine in more detail in the Problem Patterns section below.
在 JVM 规范中,堆栈帧中的局部变量没有类型,它只是一个字节数组,编译器负责为这些局部变量生成特定类型的指令,例如 iload、fload、aload 等. 很明显,GC 无法仅通过查看堆栈帧的局部变量部分来找到对对象的引用。
我的问题是:
GC 是如何找到这些根的?
GC 如何在堆栈中找到引用的局部变量 object 而不是其他类型的变量(例如 iconst 存储的变量)?
然后 Gc 如何找到那些对象的字段来创建一个可访问的 树?
是否使用JVM自己定义的指令来查找那些 对象?
最后这句话在文章中是什么意思?
This is not a real object virtual reference and thus is not visible
- How GC finds those roots at all?
JVM 提供内部 (C / C++) API 用于查找根。 JVM 知道 Java 堆栈帧在哪里,每个 Java 的静态帧 class 在哪里,实时 JNI object 句柄在哪里,等等。 (它知道,因为它参与创建它们,并跟踪它们。)
- How GC can find local variables in the stack that are references to object and are not other type of variables.
JVM 为每个方法保留信息,说明每个堆栈帧中的哪些单元格是引用变量。 GC可以找出每个堆栈帧对应的方法......就像fillInStackTrace
一样。
(for instance constant)
这实际上并不相关。常量(即 final
字段)没有得到特殊处理。
- Then how GC finds fields of those objects to create an accessible tree?
JVM 为每个 class 保留信息以说明哪些静态字段和实例字段是引用变量。每个 object 的 header 中都有一个字段引用 class.
整个过程称为“标记”,在您查看的页面中有描述。
- Does it use instruction that are defined by jvm itself to find those objects?
我不确定你在问什么。但“可能是”。 GC 是 JVM 的一个组件,所以所做的一切都是“由 JVM 定义的”。
- And lastly what is the meaning of this sentence in the article?
This is not a real object virtual reference and thus is not visible
可能是说线程的堆栈不是 Java object ... 这是真的。但我认为您需要询问该电子书的作者;他们的名字见 https://www.dynatrace.com/resources/ebooks/javabook/ 的底部。
你添加了这个:
In JVM specification local variables in the frames of stack have no type and it's just somehow an array of bytes and it's the responsibility of compiler to generate type specific instruction for those local variables for instance iload, fload, aload, etc. So clearly GC can not find references to object by only looking at local variable section of the stack frames.
事实上,事实并非如此。正如@Holder 提醒我的那样,验证者 通过模拟初始化它们的字节码的效果来推断 堆栈帧中单元格的类型。此外,class 文件中的每个方法都有一个 StackMapTable
属性,其中包含用于协助(并加快)验证程序类型确定的信息。
稍后,GC可以从JVM获取推断的类型信息。
(理论上 GC 还可以利用 StackMapTable
信息来确定局部变量何时超出范围...在一种方法。但显然它不在 HotSpot JVM 中;参见 Does the StackMapTable affect the garbage collection behavior?)
该电子书中对垃圾 collection 的描述(故意)简短而高级。但你会发现大多数描述都是如此。深层细节复杂。
如果您真的想(并且需要)了解 GC 的工作原理,我的建议是:
- 要了解当前 Java 实现的工作原理 阅读 OpenJDK 源代码。
- 追踪并阅读 Sun 和 Oracle 关于 Java GC 的研究论文。
- 找一本关于垃圾的好教科书Collection。