我正在阅读有关GC的文章,并读到当对象符合垃圾收集的条件时,GC必须在其上运行finalize
方法。 finalize
方法只能运行一次,因此GC会将对象标记为已完成,并让其休息直到下一个周期。
在finalize方法中,您可以从技术上“复活”对象,例如,通过将其分配给静态字段。该对象将再次变为活动状态,并且不符合垃圾收集的条件,因此GC将不会在下一个周期对其进行收集。
但是,该对象将被标记为finalize,因此当它再次变得合格时,将不会调用finalize方法。从本质上讲,您可以在对象的整个生命周期中仅一次旋转此“复活”技巧。
我觉得这很有趣。但是,如果我的变量是非静态的,如何在finalize
方法中将其更改为静态?
记住:
如果任何活动线程或任何静态引用都无法访问该对象,则该对象可以进行垃圾回收或GC。因此,技巧是将对象添加到finalize
方法内的静态资源中,这将仅一次防止垃圾收集。 finalize
方法是受保护的,因此无论子类是否在同一程序包中,子类都可以覆盖它们。
这是一种危险的做法,不需要在内部应用程序代码中使用。
答案 0 :(得分:1)
在运行时更改变量定义并不容易,在某些情况下几乎是不可能的。可能会有一些讨厌的反射技巧,可能涉及内联编译,类加载等,但是您不应该这样做。将变量从静态更改为非静态,反之亦然,这还涉及到移动存储中的数据并处理潜在的冲突-因此,请勿这样做。
无论如何,变量只是引用,要使对象复活,您只需要从活动线程创建新引用即可。可以使用由静态变量引用并添加了this
引用的某个集合来完成。
示例(仅出于说明目的,除非您真正知道自己在做什么并且有充分的理由,否则请不要使用它)
class NastyResurrector {
public static Collection<Object> RESURRECTED_OBJECTS = ...;// use whatever collection implementation you like
}
然后在finalize()
中打给NastyResurrector.RESURRECTED_OBJECTS.add(this)
,在那里您就可以参考。
但是,我将引用source of your question(问题Q11):
请注意,只有在您真正知道自己在做什么的情况下,才应使用此丑陋的骇客
在我看来,这是最重要的收获。