0

在 finally 块中将实例设为孤儿请求 GC 以高优先级执行垃圾收集吗?

SQLConnect ds =null;
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
...  
variables  

try {
    //Business Logic       
} catch(Exception e) {
    //Logging goes here
} finally {
    //Make instances Orphan
    ds = null;
    con = null;
    pstmt = null;
    rs = null;
}
4

5 回答 5

10

不,您正在做一些毫无意义的事情(当局部变量将不再被使用时将它们设置为 null),但您没有做您应该做的事情:关闭语句/连接。

如果你使用的是 Java 7,你应该只使用调用块,或者使用 try-with-resources 语句,这让close生活更finally简单

try (Connection conn = ...)
{
    try (PreparedStatement statement = ...)
    {
        try (ResultSet rs = ...)
        {
            ...
        }
    }
}

null为了垃圾收集而设置变量几乎是不值得的——但是调用close持有非内存资源(文件句柄、网络句柄、数据库句柄等)的实例总是一个好主意。在释放这些资源之前,您真的不想等到终结器恰好为您清理。

于 2013-06-28T06:11:16.373 回答
5

在 finally 块中将实例设为孤儿请求 GC 以高优先级执行垃圾收集吗?

不会。分配null不会改变垃圾回收对象的“优先级”。事实上,假设这些变量的作用域即将结束,分配null给它们是没有意义的。

null在Java中对某个变量或字段赋值不会减少引用计数等,也不会触发相应的对象被回收。实际上完全GC是无视赋值事件的。赋值最多只能做对象无法更快地到达。但是在这个变量即将超出范围的示例中,无论如何这几乎会立即发生。因此null分配没有实现任何东西。)

当 JVM 认为是正确的时间时,垃圾收集就会运行,而不管你做什么。除了打电话......出于其他原因System.gc(),这是一个非常糟糕的主意!


在正常情况下,您不必担心 GC 何时运行。但是,在这种情况下,您正在处理外部资源;即数据库连接、结果集等。这些需要正确“管理”,否则您可能会遇到资源泄漏问题。

如果/当对象确实被 GC'ed 时,它们可能会被它们各自的finalize方法关闭。但是,完成可能发生得太晚,无法避免资源泄漏的不良后果。

因此,管理这些的正确方法对null他们来说不是(徒劳的)希望他们能尽快被 GC 处理。处理它们的正确方法是close()finally块中显式调用它们各自的方法;例如

finally {
    conn.close();  // This should also close any child Statement and 
                   // ResultSet instances
}

一个更好的方法是使用 Jon Skeet 的回答所描述的 Java 7“尝试资源”语法。

于 2013-06-28T06:22:32.640 回答
1

java中的内存泄漏与垃圾收集器的工作频率或时间无关!

当它永远不会被再次使用并且无法释放时,内存就会泄漏。

您的问题可能与资源管理有关。处理数据库连接是管理资源的一个很好的例子,你应该考虑使用某种连接池

旁注:要获取有关 Java 中内存泄漏的信息,请访问以下问题:使用 Java 创建内存泄漏

于 2013-06-28T06:27:09.253 回答
1

请不要惹垃圾收集器。这通常会导致代码难以理解但不会提高任何性能。

只要至少有一个对象引用,垃圾收集器就不会收集该对象,无论您做什么。

如果不再引用对象,垃圾收集器将收集该对象。垃圾收集器在内存变低时运行。

请注意,某些对象(例如Connection您的情况)也是获取外部资源。每次都必须手动释放这些资源。因此,关闭块Connection中的finally比将其设置为重要得多null

于 2013-06-28T06:18:41.847 回答
0

不,绝对不。一千次没有。

Java 是一种内存管理语言。试图强制 JVM 以一种不同于它通常管理内存的方式来管理内存,这对你自己没有任何好处。这样的方案必然依赖于 JVM 实现,而不是可移植的,并且可能会给您带来比修复的问题更多的问题。

在 Java 中避免内存泄漏的最佳方法:

  • 将对象引用限制在尽可能窄的范围内。通常,您会将对象引用的范围限制为单个方法或块。一旦引用超出范围,它将有资格进行垃圾收集。

  • 仅针对代表您自己的托管内存实现的引用类型清空对象引用。在 Effective Java, 2nd Ed. 中,Joshua Bloch 给出了一个简单的引用缓存示例。当缓存缩小时,他建议将不再使用的引用清空(否则这些引用会被保留并阻止相应的对象变得有资格被收集)。他称之为“你选择管理自己的记忆”。

  • 避免将其他短期对象的引用“泄漏”到可以由长期变量保存的上下文中。内部类表示可能发生这种情况的情况。

  • 为资源密集型的长期对象释放资源。例如数据库连接和某些 GUI 控件。

只要您将引用类型限制在尽可能窄的范围内,大多数时候您就不必担心垃圾收集。

于 2013-07-14T00:50:01.377 回答