这个Java方法保护了void finalize()的问题,我试图寻找有关此问题的先前问题,但仍然无法弄清楚如何解决它, 因此,我的一个项目类正在调用此方法finalize(),该方法已从Java 9中弃用了,也许他们会在进一步的发行版中将其删除,所以我的公司想解决此问题,而我在这部分上做了工。谁能建议我如何解决这个问题,解决方案很简单,只需从类中删除该方法即可,但没人允许我这样做,因为他们不想冒险。所以我需要解决办法,
我不知道它对你们有多大的意义,我愿意寻求解决方案。
private DiskCache dc;
public void delete(DiskCacheItem item)
{
File f = file(item);
if (f != null)
{
log.debug("Delete " + f + ": " + f.delete());
}
files.remove(item);
items.remove(item);
}
private void validate()
{
dc.validate(this);
}
public void delete()
{
validate();
dc.delete(this);
}
protected void finalize()
{
try { delete(); } catch (Exception e) { }
}
答案 0 :(得分:1)
对于此类资源在使用后需要特殊处理的类,应实施AutoCloseable interface。它提供了close()方法,您可以将其放入删除代码。然后可以与try with resources pattern一起使用,如下所示:
try(YourClass yourObject = new YourClass()) {
// do work with yourObject
}
编译器会自动在最后插入一个finally块,并在其中调用yourObject.close();
以安全清理资源。
修改 一个示例类如下所示:
class MyClass implements AutoCloseable {
// create resources
@Override
public void close() throws Exception {
// delete resources here
}
}
答案 1 :(得分:1)
可以理解,简单地删除finalize()
方法存在阻力。毕竟,它正在进行一些有用的清理。问题是用什么代替它。
制作项目AutoCloseable
可能会有所帮助,尽管只有在单个词汇范围内使用该项目时,此方法才有用。这将使您能够使用try-with-resources。例如,如果未在词法范围内使用该项目,则将其插入多个数据结构中,则您不能真正使用try-with-resources。在此项目无法访问后,您可能需要在此处执行一些清理操作。
完成的首选替代方法是使用WeakReference
之类的东西。普通参考是“强”参考。当所有强引用都消失了,仅留下弱引用时,该项变为“弱可达”。这会将参考排队在参考队列上;本质上,这是一个说“该物品不再牢固可到达”的事件,接收到该事件后要采取的措施是执行一些清除操作。
这种参考处理可能很不方便,因此还有另一种称为Cleaner
的机制可能更易于使用。
使最终确定变得方便的原因是finalize()
方法位于将要收集的对象本身上。终结处理存在的问题之一是,这通过创建新的强引用来“复活”对象。
使用引用或清除程序处理的技巧是,您需要跟踪需要清除的内容,而无需保留对其关联对象的引用。在您的情况下,您有一个DiskCacheItem
,它显然保存在DiskCache
中。如果一个DiskCacheItem
实例即将被垃圾回收,您希望将其从DiskCache
中删除。从代码中很难看出来,但是清除操作似乎是要删除可能与File
关联的DiskCacheItem
对象。如果是这样,请执行以下操作:
创建一个Cleaner
实例,该实例将负责执行清理操作。
创建一个状态类,其中包含要清除的内容,在本例中为File
。
将DiskCacheItem
添加到DiskCache
时,创建状态类的实例,并在Cleaner中注册它,并将其与清理操作相关联。在这种情况下,清除操作是删除文件。这将返回Cleanable
的实例。
如果DiskCacheItem
上有明确的“关闭”或“删除”操作,请在关联的Cleanable对象上调用clean()
。这将立即调用清除操作。
在将来的某个时候,如果DiskCacheItem
未被显式删除,并且所有对它的强引用都被删除,则它将变为幻影可到达的。这将导致清理程序调用清理操作。
这有效地代替了finalization和finalize()
方法,尽管您必须为此重新安排数据结构。
所有这些之后,用Cleaner / Cleanable机制替换finalization有什么意义?首先,您可以显式清理Cleanable。当它最终变得无法访问时,它只是垃圾收集。无需额外处理。使用finalization,即使已经在逻辑上清理了finalizable对象,JVM仍需要运行finalize()方法。其次,完成操作需要额外的GC传递,以确保对象没有被“复活”。使用参考处理和清理程序,不可能“复活”对象。第三,finalization很脆弱,很难正确实现finalize()方法。