强制关闭Java中所有未关闭的资源
我的代码基本上在Apache Spark上运行,其中每个容器都在单独的JVM上运行。您为容器指定了一定的内存限制。在我的程序中,一个容器完成了一项任务,但是当它试图执行另一项任务时,它会崩溃,说超出了内存限制。如果我在单独的容器中运行每个任务,它们总是运行良好。所以,看起来在任务完成后留下了一些未关闭的资源,我无法在代码中找到它们,而这些未关闭的资源增加了容器的内存。所以,我的问题是,Java中有没有办法告诉JVM强制关闭所有资源。我也可以强制垃圾收集。我想在每项任务结束时执行这两个步骤。强制关闭Java中所有未关闭的资源
您可以运行System.gc();
但我怀疑这会帮助 - 内存不足时,将Java垃圾收集,只有失败如果这需要太长时间。但是你描述它的方式,你可能没有资源(=文件,套接字等)打开,但是大对象可达。确保返回的对象不会引用不必要的中间数据,也不会在static
变量中存储除常量之外的任何内容。
使用例如visualvm
或其他任何可以产生堆转储的内容来查找哪些对象支持您的内存。
我知道Scala没有这个功能。但Java 8具有自动闭合的外部资源,被称为尝试 - 与资源一个很好的功能:离开这个块时
try(AutoCloseable foo = openSomeResource()) {
doSomething();
}
会自动调用foo.close();
,无论怎样(例如例外,返回)。如果遵循这种模式,很难将资源保持开放。但是这指的是Java中所谓的“资源”,它们必须实现AutoCloseable
接口,您可能没有打开资源,但可访问对象。假设有很多关于如何调试Java/Scala内存泄漏的教程。但通常,第一步是获得一个堆转储以查看正在使用多少内存。某些工具(例如hprof,内置的JVM)甚至可以使用行号显示分配站点。
也许你可以使用try-与资源在JDK7以上
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
不,你真的需要小心你的程序来清理不必要的对象。 Java仅为符合GC要求的对象释放内存(但在抛出OutOfMemory错误之前它可靠地执行此操作)。 – Thilo
您可以让JVM在进入OOM时产生堆内存转储,以查看仍然存在的内容。有一个启动标志。 – Thilo
您一般无法“关闭所有未关闭的资源”,因为您的程序可能仍在使用这些资源。正如@Thilo所提到的,堆转储来分析任何实际的泄漏可能是您最好的选择。 –