我的代码基本上是在Apache Spark上运行的,其中每个容器都在一个单独的JVM上运行。您为容器指定了某个内存限制。在我的程序中,一个容器完成了一个任务,但是当它试图执行另一个任务时,它会崩溃,说超出了内存限制。如果我在一个单独的容器中运行每个任务,它们总是正常运行。因此,看起来任务完成后会留下一些未封闭的资源,我无法在代码中找到,而那些未封闭的资源会增加容器的内存。所以,我的问题是,Java中是否有任何方法可以告诉JVM强制关闭所有资源。我还可以强制垃圾收集吗?我想在每项任务结束时执行这两个步骤。
答案 0 :(得分:2)
你可以运行System.gc();
,但我怀疑它会有所帮助 - 当内存不足时,Java会垃圾收集,只有在这需要太长时间才会失败。但是你描述的方式,你可能没有资源(=文件,套接字等)打开,但是大对象可以 。确保返回的对象不引用不必要的中间数据,并且不在static
变量中存储除常量之外的任何内容。
使用例如visualvm
或其他任何可以产生堆转储的内容,以查找占用内存的对象。
我知道Scala没有此功能。但Java 8有一个很好的功能,可以自动关闭外部资源,称为try-with-resources:
try(AutoCloseable foo = openSomeResource()) {
doSomething();
}
离开此区块时,会自动调用foo.close();
,无论如何(例如,异常,返回)。如果你遵循这种模式,就很难让资源保持开放状态。但这指的是Java中所谓的“资源”,它们必须实现AutoCloseable
接口,您可能没有资源打开,但可以访问的对象。据说有很多关于如何调试Java / Scala内存泄漏的教程。但通常第一步是获取堆转储以查看正在使用多少内存。某些工具(例如hprof,内置JVM)甚至可以使用行号显示分配站点。
答案 1 :(得分:0)
也许你可以在jdk7或更多版本中使用try-with-resources
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}