.net 根源是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6366211/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What are the roots?
提问by DarthVader
What are the roots in garbage collection?
垃圾收集的根源是什么?
I have read the definition of root as "any reference that you program can access to" and definition of live is that an object that is being used, which can be a local variable, static variable.
我已经将 root 的定义读为“您程序可以访问的任何引用”,而 live 的定义是正在使用的对象,它可以是局部变量、静态变量。
I m little confused with discriminating the difference between root and live objects.
我对区分根对象和活动对象之间的区别并不感到困惑。
What is path to root? How does root and live objects work?
什么是root路径?根对象和活动对象如何工作?
Can someone elaborate ?
有人可以详细说明吗?
回答by aib
If you think of the objects in memory as a tree, the "roots" would be the root nodes - every object immediately accessible by your program.
如果您将内存中的对象视为一棵树,那么“根”将是根节点 - 您的程序可以立即访问每个对象。
Person p = new Person();
p.car = new Car(RED);
p.car.engine = new Engine();
p.car.horn = new AnnoyingHorn();
There are four objects; a person, a red car, its engine and horn. Draw the reference graph:
有四个对象;一个人,一辆红色汽车,它的发动机和喇叭。绘制参考图:
Person [p]
|
Car (red)
/ \
Engine AnnoyingHorn
And you'll end up with Personat the "root" of the tree. It's live because it's referenced by a local variable, p, which the program might use at any time to refer to the Personobject. This also goes for the other objects, through p.car, p.car.engine, etc.
你最终会Person在树的“根”处。它是活动的,因为它被局部变量 引用,p程序可能随时使用它来引用Person对象。这也无二的其他对象,通过p.car,p.car.engine等等。
Since Personand all other objects recursively connected to it are live, there would be trouble if the GC collected them.
由于Person和所有其他递归连接到它的对象都是活动的,如果 GC 收集它们就会有麻烦。
Consider, however, if the following is run after a while:
但是,请考虑是否在一段时间后运行以下内容:
p.car = new Car(BLUE);
And redraw the graph:
并重新绘制图形:
Person [p]
|
Car (blue) Car (red)
/ \
Engine AnnoyingHorn
Now the Personis accessible through pand the blue car through p.car, but there is no way the red car or its parts can ever be accessed again - they are not connected to a live root. They can be safely collected.
现在Person可以通过 访问p,蓝色汽车通过p.car,但是红色汽车或其部件无法再次访问 - 它们没有连接到活动根。它们可以安全地收集。
So it's really a matter of taking every starting point (every local variable, globals, statics, everything in other threads and stack frames) — every root — and recursively following all the references to make up a list of all the "live" objects: objects which are in use and unsuitable for deletion. Everything else is garbage, waiting to be collected.
因此,这实际上是获取每个起点(每个局部变量、全局变量、静态变量、其他线程和堆栈帧中的所有内容)——每个根——并递归跟踪所有引用以组成所有“活动”对象的列表的问题:正在使用且不适合删除的对象。其他一切都是垃圾,等待被收集。
回答by DarthVader
The GC (Garbage Collector) roots are objects special for garbage collector. The Garbage Collector collects those objects that are not GC roots and are not accessible by references from GC roots.
GC(垃圾收集器)根是垃圾收集器专用的对象。垃圾收集器收集那些不是 GC 根并且不能通过来自 GC 根的引用访问的对象。
There are several kinds of GC roots. One object can belong to more than one kind of root. The root kinds are:
有几种 GC 根。一个对象可以属于一种以上的根。根的种类是:
- Class - class loaded by system class loader. Such classes can never be unloaded. They can hold objects via static fields. Please note that classes loaded by custom class loaders are not roots, unless corresponding instances of java.lang.Class happen to be roots of other kind(s).
- Thread - live thread
- Stack Local - local variable or parameter of Java method
- JNI Local - local variable or parameter of JNI method
- JNI Global - global JNI reference
- Monitor Used - objects used as a monitor for synchronization
- Held by JVM - objects held from garbage collection by JVM for its purposes. Actually the list of such objects depends on JVM implementation. Possible known cases are: the system class loader, a few important exception classes which the JVM knows about, a few pre-allocated objects for exception handling, and custom class loaders when they are in the process of loading classes. Unfortunately, JVM provides absolutely no additional detail for such objects. Thus it is up to the analyst to decide to which case a certain "Held by JVM" belongs.
- 类 - 由系统类加载器加载的类。此类类永远无法卸载。它们可以通过静态字段保存对象。请注意,自定义类加载器加载的类不是根,除非 java.lang.Class 的相应实例碰巧是其他类型的根。
- 线程 - 活动线程
- Stack Local - Java 方法的局部变量或参数
- JNI Local - JNI 方法的局部变量或参数
- JNI Global - 全局 JNI 参考
- Monitor Used - 用作同步监视器的对象
- 由 JVM 持有 - JVM 出于其目的从垃圾收集中持有的对象。实际上,此类对象的列表取决于 JVM 实现。可能的已知情况有:系统类加载器、JVM 知道的一些重要异常类、一些用于异常处理的预分配对象,以及加载类过程中的自定义类加载器。不幸的是,JVM 绝对没有为这些对象提供额外的细节。因此,由分析师决定某个“由 JVM 持有”属于哪种情况。
(credit to YourKit's website)
(归功于YourKit 的网站)
Not mentioned by YourKit is the fact that objects awaiting finalization will be retained as roots until the GC runs the finalize()method. That can cause transient retention of large graphs somewhat unexpectedly. The general rule of thumb is not to use finalizers (but that's a different question).
YourKit 没有提到的是,等待终结的对象将作为根保留,直到 GC 运行该finalize()方法。这可能会导致大图的暂时保留有点出乎意料。一般的经验法则是不使用终结器(但这是一个不同的问题)。
回答by Vineet Reynolds
Roots or garbage collection roots are the objects that are always reachable. If an object is always reachable, then it is not eligible for garbage collection; roots therefore are always ineligible for collection. It is the initial set of objects from where reachability of all other objects on the heap are determined.
根或垃圾收集根是始终可达的对象。如果一个对象总是可达的,那么它就没有资格进行垃圾回收;因此,根始终没有资格收集。它是确定堆上所有其他对象的可达性的初始对象集。
Other objects on the heap reachable from the garbage collection roots are considered to be live objects, and ineligible for collection; the objects that are unreachable can be marked for reclamation.
可从垃圾收集根访问的堆上的其他对象被认为是活动对象,并且不符合收集条件;无法访问的对象可以标记为回收。
I know Java more than the .Net platform, so I'll speak only for one. On the Java platform, the GC roots are actually implementation dependent. In most runtime however, the GC roots tend to be the operands on the stack (for they are currently in use by threads) and class (static) members of classes. Reachability is calculated from these objects in most JVMs. There are other cases where local parameters and operands used by JNI calls will be considered part of the root set, and also used to calculate reachability.
我对 Java 的了解比 .Net 平台还多,所以我只说一个。在 Java 平台上,GC 根实际上是依赖于实现的。然而,在大多数运行时,GC 根往往是堆栈上的操作数(因为它们当前被线程使用)和类的类(静态)成员。在大多数 JVM 中,可达性是根据这些对象计算的。在其他情况下,JNI 调用使用的本地参数和操作数将被视为根集的一部分,也用于计算可达性。
I hope this clears any lingering doubts over what is a root (set) and what is a live object.
我希望这可以消除对什么是根(集)和什么是活动对象的任何挥之不去的疑虑。
回答by Lawrence Dol
The IBM web sitelists the following as GC roots.
在IBM的网站列出了以下为GC根。
Note that some of these are artificial constructs done by a memory analyzer, but still important to be aware of if you are looking at a heap dump.
请注意,其中一些是由内存分析器完成的人工构造,但如果您正在查看堆转储,请注意仍然很重要。
System class
A class that was loaded by the bootstrap loader, or the system class loader. For example, this category includes all classes in the rt.jar file (part of the Java runtime environment), such as those in the java.util.* package.
JNI local
A local variable in native code, for example user-defined JNI code or JVM internal code.
JNI global
A global variable in native code, for example user-defined JNI code or JVM internal code.
Thread block
An object that was referenced from an active thread block.
Thread
A running thread.
Busy monitor
Everything that called the wait() or notify() methods, or that is synchronized, for example by calling the synchronized(Object) method or by entering a synchronized method. If the method was static, the root is a class, otherwise it is an object.
Java local
A local variable. For example, input parameters, or locally created objects of methods that are still in the stack of a thread. Native stack
Input or output parameters in native code, for example user-defined JNI code or JVM internal code. Many methods have native parts, and the objects that are handled as method parameters become garbage collection roots. For example, parameters used for file, network, I/O, or reflection operations.
Finalizer
An object that is in a queue, waiting for a finalizer to run.
Unfinalized
An object that has a finalize method, but was not finalized, and is not yet on the finalizer queue.
Unreachable
An object that is unreachable from any other root, but was marked as a root by Memory Analyzer so that the object can be included in an analysis.
Unreachable objects are often the result of optimizations in the garbage collection algorithm. For example, an object might be a candidate for garbage collection, but be so small that the garbage collection process would be too expensive. In this case, the object might not be garbage collected, and might remain as an unreachable object.
By default, unreachable objects are excluded when Memory Analyzer parses the heap dump. These objects are therefore not shown in the histogram, dominator tree, or query results. You can change this behavior by clicking File > Preferences... > IBM Diagnostic Tools for Java - Memory Analyzer, then selecting the Keep unreachable objects check box.
Java stack frame
A Java stack frame, which holds local variables. This type of garbage collection root is only generated if you set the Preferences to treat Java stack frames as objects. For more information, see Java Basics: Threads and thread stack queries.
Unknown
An object of unknown root type. Some dumps, such as IBM Portable Heap Dump (.phd) files, do not have root information. In this case, the Memory Analyzer parser marks objects that have no inbound references, or are unreachable from any other root, as unknown. This action ensures that Memory Analyzer retains all the objects in the dump.
系统类
由引导加载程序或系统类加载器加载的类。例如,此类别包括 rt.jar 文件(Java 运行时环境的一部分)中的所有类,例如 java.util.* 包中的类。
JNI本地
本机代码中的局部变量,例如用户定义的 JNI 代码或 JVM 内部代码。
JNI全球
本机代码中的全局变量,例如用户定义的 JNI 代码或 JVM 内部代码。
线程块
从活动线程块引用的对象。
线
一个正在运行的线程。
忙监控
调用wait() 或notify() 方法或同步的所有内容,例如通过调用synchronized(Object) 方法或输入同步方法。如果方法是静态的,则根是一个类,否则它是一个对象。
Java本地
一个局部变量。例如,仍然在线程堆栈中的输入参数或本地创建的方法对象。原生堆栈
本机代码中的输入或输出参数,例如用户定义的 JNI 代码或 JVM 内部代码。许多方法都有本机部分,作为方法参数处理的对象成为垃圾收集根。例如,用于文件、网络、I/O 或反射操作的参数。
终结器
在队列中等待终结器运行的对象。
未定稿
具有终结方法但尚未终结且尚未在终结器队列中的对象。
不可达
无法从任何其他根访问的对象,但被内存分析器标记为根,以便该对象可以包含在分析中。
无法访问的对象通常是垃圾收集算法优化的结果。例如,一个对象可能是垃圾收集的候选对象,但它太小以至于垃圾收集过程会太昂贵。在这种情况下,该对象可能不会被垃圾回收,并且可能会保留为无法访问的对象。
默认情况下,内存分析器解析堆转储时会排除无法访问的对象。因此,这些对象不会显示在直方图、支配树或查询结果中。您可以通过单击 File > Preferences... > IBM Diagnostic Tools for Java - Memory Analyzer,然后选中 Keep unreachable objects 复选框来更改此行为。
Java堆栈帧
一个 Java 堆栈帧,其中包含局部变量。仅当您设置首选项以将 Java 堆栈帧视为对象时,才会生成这种类型的垃圾回收根。有关更多信息,请参阅 Java 基础知识:线程和线程堆栈查询。
未知
未知根类型的对象。某些转储,例如 IBM Portable Heap Dump (.phd) 文件,没有根信息。在这种情况下,内存分析器解析器将没有入站引用或无法从任何其他根访问的对象标记为未知。此操作可确保内存分析器保留转储中的所有对象。
回答by irreputable
In java I would say threads are the root objects. Every live object can be back traced to a live thread. For example, a static object is referenced by a class, which is referenced by a class loader, which is referenced by another class, which is referenced by an instance of that class, ... which is referenced by a Runnable, which is referenced by a live thread. (Note, classes can be GC'ed, they can't be roots)
在 Java 中,我会说线程是根对象。每个活动对象都可以追溯到一个活动线程。例如,一个静态对象被一个类引用,该类被类加载器引用,该类被另一个类引用,该类被该类的一个实例引用,...通过实时线程。(注意,类可以被 GC 处理,它们不能是根)
We can also consider a "real" root for all threads, however that is out of the realm of standard Java. We can't say what it is, and how it references all the threads.
我们也可以考虑所有线程的“真实”根,但这超出了标准 Java 的范围。我们不能说它是什么,以及它如何引用所有线程。

