在下面的代码,因为amethod
被调用。 在什么点/线最初是由引用的对象myObject
,符合垃圾回收?
class Test {
private Object classObject;
public void amethod() {
Object myObject = new Object();
classObject = myObject;
myObject = null;
}
}
如果classObject
或amethod
有公共,保护,默认或静态的访问修饰符,它会影响到什么点的对象是符合垃圾回收? 如果是的话,会是怎样的影响?
- 我首先想到的是,对象是符合垃圾收集当测试对象进行垃圾回收。
- 但话又说回来。 优化程序可能知道classObject决不会从在这种情况下读
classObject = myObject;
将被优化并myObject = null;
是它是符合垃圾回收点。
直到所有对它的引用被丢弃的对象将不会成为垃圾回收的候选者。 Java对象是通过参考分配,所以当你有
classObject = myObject;
您分配另一个引用堆上的同一个对象。 所以这条线
myObject = null;
只有摆脱的一个参考。 为了使myObject
垃圾收集的候选人,你必须有
classObject = null;
这实际上是由Java语言规范准确地处理, §12.6.1,实现定稿 :
一个程序的优化转换可以设计降低可达小于那些会天真地被认为是可到达的对象的数量。 例如,一个Java编译器或代码生成器可以选择设置将不再被用于变量或参数null
,以使存储对这样的对象是潜在可回收越快。
如果在对象的字段中的值被存储在寄存器发生的另一个例子。 然后该程序可以访问寄存器,而不是对象,永远不会再访问该对象。 这将意味着,对象是垃圾。 ...
但
......需要注意的是这种优化的,如果引用是在栈上只允许,不存储在堆中。
例如,考虑终结守护模式:
class Foo { private final Object finalizerGuardian = new Object() { protected void finalize() throws Throwable { /* finalize outer Foo object */ } } }
终结监护人力super.finalize
如果子类重写被称为finalize
,不显式调用super.finalize
。
如果这些优化允许为存储在堆中引用,那么Java编译器可以检测到finalizerGuardian
场从来不看,空出来,立刻收集对象,早打电话来终结。 这违背了原意:程序员可能想叫Foo
终结时Foo
实例变得无法访问。 因此,这种转变是不合法的:内部类对象应该是可达的,只要外部类对象可达。
这个例子可以应用1:1到你的榜样,只要对象是通过实例字段引用classObject
,它不能作为垃圾早于收集Test
包含的参考实例。
但请注意,在说明书中提到的积极的优化仍然是允许的,当被应用到使用的代码Test
实例。 早期的超预期征收可能发生,只要双方的Test
实例和引用的对象被收集在一起。 在这种情况下,在所指定的以下方面§12.6适用:
Java编程语言强加给finalize方法调用没有顺序。 终结可以以任意顺序被调用,甚至同时进行。
所以这是完全有可能的Test
实例早于所引用的对象收集classObject
而“内部”对象的终结较早调用。 这是保证,唯一的一点是,使内对象的终结器运行时,外部对象不可达(或有挂起的或并发的终结)。 因为在你的榜样,既没有一个不平凡的终结,这并不怎样都无所谓......
你的想法是,私有对象可以马上GC'd因为没有其他的代码可以访问它确实有一定的牵引力,而这将与Java的内存管理的一般语义混乱。 例如,如果对象实现finalize
,当一个对象符合垃圾收集的Java语义明确规定,即释放方法将有被称为对规范。
另外请注意,又将对象可以引用其他对象,甚至更复杂的可能结果。 更何况对象是通过反射随时随地访问,并会作出观察没有意义的领域突然改变对null
,即使没有代码可能已经作出分配。
总之,有很多原因,您的优化的想法也不会在更广泛的绘画作品。
从图书OCA Java SE 7中
一个对象被标记为有资格进行垃圾回收,当它不能再被访问,当对象超出范围可发生。 它也可以发生在一个对象的引用变量被分配了一个明确的空值或重新初始化。
没有对象符合垃圾收集在这里,因为你正在创建为同一对象两个参考和你仅一个参考给空但其他引用仍然指向你的对象
既然你拿着myObject
在classObject
( 参考保持不变 ),直到它的实例(对象通过classObject引用的内存)将不进行垃圾回收Test
被释放/卸载。
在下面的代码,因为已经amethod方法被调用。 在什么点/线最初是由myObject的引用的对象,符合垃圾回收?
你的问题是没有意义的,因为有你的高层次的源代码和低级表示脱节(寄存器全球根,在堆栈和全局变量)垃圾收集器看到。
你的那句“符合垃圾回收”大概意味着在什么时候的内存堆分配块不可达。 所以你的问题只能通过做大量的(可疑)假设什么堆分配多久生成的代码会继续引用来回答。