将非静态变量更改为静态变量



我正在阅读有关GC的信息,并读到当对象符合垃圾回收条件时,GC必须对其运行finalize方法。finalize方法保证只运行一次,因此 GC 将对象标记为最终完成,并让它休息,直到下一个循环。

在 finalize 方法中,您可以在技术上"复活"对象,例如,通过将其分配给静态字段。该对象将再次变为活动状态,并且不符合垃圾回收条件,因此 GC 不会在下一个周期中收集它。

但是,该对象将被标记为已确定,因此当它再次符合条件时,将不会调用 finalize 方法。从本质上讲,在对象的生命周期内,您只能将这种"复活"技巧旋转一次。

我觉得这很吸引人。但是,如果我的变量是非静态的,如何在finalize方法中将其更改为静态变量?

记得:

如果无法从任何活动线程或任何静态引用访问对象,则该对象将有资格进行垃圾回收或 GC。因此,黑客是将对象添加到finalize方法中的静态资源中,这将仅阻止一次垃圾回收。finalize方法受到保护,因此可以被子类覆盖,无论它们是否在同一包中。

这是一种危险的做法,无需在应用程序代码中使用。

在运行时更改变量定义并不容易,在某些情况下几乎是不可能的。可能会有一些令人讨厌的反射技巧,可能涉及内联编译、类加载等,但你不应该这样做。将变量从静态更改为非静态,反之亦然,这也涉及在存储中移动数据并处理潜在的冲突 - 所以不要这样做。

无论如何,变量只是引用,要复活一个对象,你只需要从实时线程创建一个新的引用。这可以通过静态变量引用的一些集合来完成,并将this引用添加到该集合。

示例(仅用于说明目的,除非您真的知道自己在做什么并且有充分的理由,否则不要使用它):

class NastyResurrector {
public static Collection<Object> RESURRECTED_OBJECTS = ...;// use whatever collection implementation you like
}

然后在finalize()你会打电话给NastyResurrector.RESURRECTED_OBJECTS.add(this),在那里你有你的参考。

但是,我将引用您问题的来源(问题Q11):

请注意,只有当你真的知道自己在做什么时,才应该使用这个丑陋的黑客。

在我看来,这是最重要的一点。

最新更新