我正在阅读有关GC的内容并读取当一个对象符合垃圾收集条件时,GC必须在其上运行finalize
方法。 finalize
方法保证只运行一次,因此GC将对象标记为最终化并使其休息直到下一个循环。
在finalize方法中,您可以在技术上“复活”对象,例如,通过将其指定给静态字段。该对象将再次生效并且不符合垃圾收集条件,因此GC不会在下一个周期中收集它。
但是,该对象将被标记为已完成,因此当它再次符合条件时,将不会调用finalize方法。从本质上讲,你可以在对象的生命周期中只转换一次“复活”技巧。
我发现这很吸引人。但是,如果我的变量是非静态的,如何将其更改为finalize
方法中的静态?
记得:
如果无法从任何活动线程或任何静态引用访问对象,则该对象符合垃圾收集或GC的条件。因此,hack是将对象添加到finalize
方法内的静态资源,这将仅防止垃圾收集一次。 finalize
方法受到保护,因此可以被子类覆盖,无论它们是否在同一个包中。
这是一种危险的做法,无需使用内部应用程序代码。
在运行时更改变量定义并不容易,在某些情况下几乎不可能。可能有一些讨厌的反射技巧可能涉及内联编译,类加载等,但你不应该这样做。将变量从静态变为非静态或反之亦然还需要在存储中移动数据并处理潜在的冲突 - 所以不要这样做。
无论如何变量只是引用和复活一个对象,你只需要从一个活动线程创建一个新的引用。这可以通过一些静态变量引用的集合来完成,并且添加了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):
请注意,只有当你真正知道自己在做什么时,才应该使用这个丑陋的黑客
这是我认为最重要的内容。