DeleteOnExitHook

时间:2016-10-18 22:34:15

标签: java memory-leaks out-of-memory akka

我有一个全天候运行的Java应用程序,它连接到MySQL服务器和TimerTask(运行Akka)。经过一周或更短的操作后,我遇到了OutOfMemoryError,堆转储显示了一个包含超过4百万个字符串的LinkedHashMap,它们使用800 MB堆的java.io.DeleteOnExitHook的GC根目录。

所有字符串都类似于/tmp/jar_cachexxxx.tmp

这个问题在运行OpenJDK Runtime Environment(build 1.8.0_101-b13)的两台机器上是一致的。 JDBC驱动程序是maven“mysql-connector-java”版本5.1.38上提供的驱动程序,我使用的是连接池BoneCP,版本0.8.0。

任何人都知道这个漏洞吗?

更新 - 2016年12月5日

在我们更改了项目的编译器之后,问题已经解决了。我们注意到eclipse jar创建者是唯一与jar缓存有任何关系的东西,所以在用maven编译项目之后,内存泄漏就消失了。

4 个答案:

答案 0 :(得分:7)

这是一个长期存在且众所周知的错误,多年来已经向Sun / Oracle报告了很多次。当前的错误号是JDK-4872014

问题在于,每次使用delete-on-exit API时,文件都会存储到printCanvas中。由于在长时间运行的服务器中,您的代码很少会故意退出,因此如果您使用大量临时文件执行此操作,则地图可以无限制地增长。

本质上,API不适用于长时间运行的服务器,因为它并不是真的打算以这种方式使用。如果您需要此功能,您需要自己实现它并按计划运行清理,以某种方式知道哪些文件可以删除。

答案 1 :(得分:1)

只有当您使用eclipse导出程序“Runnable JAR file”然后选择“将所需库打包到生成的JAR中”时才会发生。

然后将使用eclipse JAR-in-JAR类加载器,它使用URLClassloader,根据这个问题会产生内存泄漏: How long are resources used (file descriptor and memory) for Java temporary files (jar_cache####.tmp)?

答案 2 :(得分:0)

您的应用程序中的某些内容正在使用File.deleteOnExit。但是由于您的应用程序永远不存在,Java必须跟踪所有这些文件,因为它们需要在最终退出时被删除(从未发生过)。 我建议您使用调试器找出应用程序的哪个部分,然后找到替代方案。

答案 3 :(得分:0)

文件的路径名中还有一个线索:“/ tmp / jar_cachexxxx.tmp”。

显然,当URLClassloader下载远程JAR文件并加载它时,会创建这些文件。如果你有数百万这些字符串,这意味着你经常这样做。