关于实例变量,尤其是字段,我在GC方面有些困惑。
因此,如果对象持有对其字段对象的引用,则在对象本身可以引用之前,这些对象将不符合垃圾回收的条件。由于Threads are GC roots并且每个对象必须仅在某个线程上创建,因此thread won't let go of any objects created on it以及来自线程的整个对象层次结构在收集垃圾之前应保留相当长的时间。
另一方面,如果对象放开了字段对象,则为这些对象调用getter方法将导致稍后返回null。
那么,这里的事实是什么?
对“现场物体”的说明(如评论中所述)
编辑2:详细说明
因此,您看到线程是通过Thread对象实例在内存中具有表示形式的执行单元。任何发生在任何地方的代码执行都发生在某个线程上。
这种处决如何发生?
通过方法中的某些代码执行。将使该对象创建什么?
而且,这将使其成为GC根。
顺便说一句,对于方法调用,该特定调用有一个堆栈,这就是我在这里所指的。
答案 0 :(得分:0)
这并不像@ louis-wasserman所说的那么简单-“是的,自然” 或就这件事而言,不是 natural ..(?)
我调查了更多内容,并在...可能的预期位置找到了答案- Java Language Specification
2.7。对象表示
Java虚拟机不要求任何特定的内部 对象的结构。
在Oracle对Java虚拟机的某些实现中, 引用类实例是指向本身的句柄的指针 一对指针:一个指向包含该方法的表的指针 对象和一个指向Class对象的指针,该对象表示类型 对象,另一个对象从堆分配给的内存 对象数据。
是的,它解决了。即使JLS并不强制使用java.lang.Object
的内部结构,也可能会使用类似于Oracle JVM的结构。
您可能会认为这意味着更大的含义。想象一个非常很重的对象,其中包含一个非常庞大的成员字段对象。嗯...可能是Bitmap
。一个10MB的位图和另一个对象仅保留图像的标题:
bulky_object = {位图,标题}
如果您将此对象创建为嵌套范围内方法内部的局部变量(例如,缘故),则在范围结束后容器对象就有资格进行垃圾回收,但是如果您决定保留对位图的引用(字段)对象在作用域之后,包含的对象将不会被完全收集:
void someMethod(){
// Outer block of the method
bitmap_ref;
// Nested block starts
{
some_object = new some_object();
// Hold a ref to the bitmap
bitmap_ref = some_object.bitmap;
}
// Nested block has ended. some_object is eligible for GC and is not accessible as a GC root
// anymore
// bitmap_ref shall remain available alive and well here as we are holding a ref to it
// Also, some_object garbage collection may have happened leaving bitmap_ref alive
}
这似乎是一个对象泄漏。