java - 将非静态变量更改为静态变量
问题描述
我正在阅读有关 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)
,你有你的参考。
但是,我将引用您问题的来源(问题 Q11):
请注意,只有在您真正知道自己在做什么时才应该使用这种丑陋的技巧
这是我认为最重要的收获。
推荐阅读
- flutter - TabView does not preserve state when swiping from one tab to another
- flutter - Responsive Column to Row depending on content size
- php - 如何从 WooCommerce 结帐表单中获取自定义数据以计算运费
- python - Tkinter 滚动条未在画布 python 上执行滚动操作
- kubernetes - 拨打 tcp 127.0.0.1:8080:连接:连接被拒绝 AWS CodeBuild EKS
- javascript - 将 html 文件转换为 jpg/png
- python - 如何使用命令在 Linux 中同时运行相同的 python 代码
- mysql - 在 sequelize 中使用带或条件的 where 子句
- python - Pygame 玩家移动
- java - org.hibernate.exception.SQLGrammarException:无法在 heroku 中提取 ResultSet