【问题标题】:what to use instead of finalize() in java在 java 中用什么代替 finalize()
【发布时间】:2020-03-20 00:07:43
【问题描述】:

让我们考虑以下代码:

class Table {
 private static int number_of_Tables=0;
 public Table(){
  ++number_of_Tables;
 }
 public void finalize(){
 --number_of_Tables; 
 }
 public static int current_TableCount(){
  return number_of_Tables;
 }
}

我想要实现的是,当垃圾收集器 (GC) 销毁对象时,可用对象的数量减少一。

但是这里关于finalize() 主题的每个人都说使用这种方法非常糟糕,因为可能会发生以下情况:即使没有指向对象的引用,GC 也可能不会立即销毁它,因为 GC 无法解决时钟,即 GC 将在一定数量的对象被销毁后被调用,即在特定时间 GC 将执行清理,这意味着即使对象不再可用,我的计数器也不会减少,我会给出错误调用方法curret_TableCount()时的信息

人们会做什么来确定地解决这类问题?

Java 中一定有某种解决方案?

编辑:我需要识别何时不再引用该对象,即在运行时甚至不存在一个指向该对象的指针(引用),当这是真的时,我会减少那种对象一个。

【问题讨论】:

  • 我想你想要 PhantomReference。
  • 我不知道这存在谢谢
  • 另见 Cleaner(在 Java 9 中添加)。注意Object#finalize() was deprecated in Java 9.
  • PhantomReferenceCleaner 都不能解决垃圾收集器只在需要内存时才运行的普遍问题。如果您需要一个可靠的正在使用对象的计数器,您需要像close()dispose() 这样的方法,应用程序代码在使用该对象后必须调用该方法。您的代码还演示了为什么像 finalize() 这样看起来易于使用的方法是 Java 的一个巨大设计错误。 finalize() 方法将被未指定的线程调用(如果有的话),因此,需要将这样的计数器设为线程安全的。
  • 在您获得关于使用什么的好答案之前,我们需要知道究竟为什么您想要更新number_of_Tables?你对这些信息做什么。了解这一点将有助于我们了解是否有其他更好的方法。

标签: java garbage-collection static-members finalize


【解决方案1】:

…可能会发生以下情况:即使没有指向对象的引用,GC 也可能不会立即销毁它,因为 GC 不能全天候工作

没错。垃圾收集器的目的是管理内存并且管理内存。只要没有内存需求,垃圾收集器就不需要运行。当内存足够时,应用程序完全有可能在没有任何 gc 循环的情况下完全运行。

此外,不能保证垃圾收集器运行会识别所有无法访问的对象。当它识别出足够的可回收内存以允许应用程序继续运行时,它可能会停止工作。

然而,这不是唯一的问题。经常被忽视的事实是,垃圾收集器只关心内存需求,这意味着即使对象正在使用中,当它的 内存 不再需要时也可能被收集,这可以通过优化代码实现。这不是理论上的问题。例如,请参阅 this bugthat bug 与对终结的天真依赖相关,即使在 JDK 代码中也是如此。

请注意,即使 finalize() 恰好在正确的时间被调用,它也会被未指定的线程调用,这需要使用线程安全构造。

人们会做什么来确定地解决这类问题?

人们通常没有这种问题。如果您真正管理非内存资源,则应使用显式清理操作,即在使用后调用类似dispose()close() 的方法。直接的方法是让类实现AutoClosable(或其子类型)并使用the try-with-resources statement

垃圾收集器触发的清理操作只是处理忘记显式清理的情况的最后手段。如前所述,实施它们需要特别小心。

如果计数器仅用于统计信息,您可能会接受它不精确的事实。通常,您不需要知道一个类有多少个实例。如果你真的需要它,例如在尝试调试内存泄漏时,您可以进行堆转储、所有现有对象的快照,并使用专用的分析工具。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-01
    • 1970-01-01
    • 2014-04-28
    • 1970-01-01
    • 2020-05-15
    • 1970-01-01
    • 2019-10-02
    相关资源
    最近更新 更多