【问题标题】:Can you count on .finalize() to be called?你能指望 .finalize() 被调用吗?
【发布时间】:2011-12-14 07:54:16
【问题描述】:

我试图检测我的一些 Java 代码以确保正确地对对象进行垃圾回收,但令人惊讶的是,它并没有像我预期的那样经常被调用。

我现在想知道这是因为仪器故障还是我需要解决的实际内存泄漏。 VisualVM 分析器似乎表明前者。

担心的情况是我有一个处理请求的线程,并且在请求中创建了数千个临时对象。有时,该线程写入的套接字意外关闭,线程遇到异常并死亡。

当线程死亡时,似乎不会在这些对象上调用 .finalize() 。这是不信任我的仪器的理由吗?

【问题讨论】:

  • 你有一个简单的、独立的例子来展示这种行为吗?
  • @aix:是的,当然,他遇到了涉及数千个对象、网络访问和意外套接字关闭的情况。他不知道问题出在哪里,顺便说一句,正是他来这里问他的问题的原因......但是他应该简单地写一个独立的例子来重现这个问题。老实说,这个“SSCCE 议程”起源于 Usenet 上的 comp.lang.java(并且已经被在 SO 上推它的同一个人推到了那里),越来越累了……我的意思是,说真的,你阅读这个问题了吗? 写一个SSCCE来重现这个怎么样?
  • @CedricMartin:冷静点。我认为这是一个合理的问题。如果答案是否定的,那么答案是否定的。没有理由对无事如此着迷。

标签: java garbage-collection


【解决方案1】:

没有。不能保证它会被调用。但是,通常会调用它。可能是你没有正确释放你的对象,或者垃圾收集器没有运行,或者终结器线程正在等待一个好的运行时间。

您可以在语言规范的Finalization of Class Instances 部分了解它。

【讨论】:

    【解决方案2】:

    Finalize() 不是解决方案。您无法知道何时会调用终结器(如果有)。如果您的问题是异常,请使用 try/catch/finally 块并关闭/清理您想要在 finally 块中关闭的所有内容。这保证了在两种情况下都将被清除:逻辑正常终止或抛出异常。

    【讨论】:

      【解决方案3】:

      根据我阅读的有关 Java 基础知识的所有内容,您应该永远依赖 finalize 来运行。 finalize() 不是析构函数,您可能从其他语言中知道。

      来自 java.lang.Object javadoc:

      The Java programming language does not guarantee which thread will invoke the finalize method for any given object.
      

      http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Object.html#finalize()

      在我看来,可怕的 finalize 应该并且仅在您在应用程序中包含一些本机代码时才使用。但即便如此,请务必不要依赖它。

      【讨论】:

        【解决方案4】:

        您的困惑似乎是是否存在内存泄漏。您试图通过查看是否调用了 finalize() 来确定这一点。如果是这样,那么检查是否存在内存泄漏是不正确的。

        我们很清楚,在 Java 中,memory leaks 主要意味着对您不需要的对象的隐藏引用。

        finalize() 的目的是让开发人员有机会清理自己的烂摊子(连接、流等)。内存应该是 JVM 的混乱/头痛并由 GC 清理。

        简而言之,“GC 保证调用 finalize() 之前会释放内存”这一事实不应解释为“如果不调用 finalize(),则存在内存泄漏”。可能只是因为该对象还没有被垃圾回收。

        如果您要查找内存泄漏,请使用工具。查看选项:

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-12-05
          • 2011-11-20
          • 2014-02-06
          • 1970-01-01
          • 2018-10-06
          • 1970-01-01
          • 2011-01-17
          • 2018-04-19
          相关资源
          最近更新 更多