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

时间:2019-02-21 10:06:38

标签: java garbage-collection jvm metaspace

我正在阅读有关GC的文章,并读到当对象符合垃圾收集的条件时,GC必须在其上运行finalize方法。 finalize方法只能运行一次,因此GC会将对象标记为已完成,并让其休息直到下一个周期。

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

但是,该对象将被标记为finalize,因此当它再次变得合格时,将不会调用finalize方法。从本质上讲,您可以在对象的整个生命周期中仅一次旋转此“复活”技巧。

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

记住:

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

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

1 个答案:

答案 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):

  

请注意,只有在您真正知道自己在做什么的情况下,才应使用此丑陋的骇客

在我看来,这是最重要的收获。