JAVAEE - 使用的堆内存只会继续增加,直到一切都中断

时间:2016-05-27 13:21:57

标签: java memory garbage-collection resource-leak

我在tomcat下运行一个中等大小的平针织网页应用程序。我发现应用程序在执行了一段时间后(几天)由于内存不足问题而继续崩溃,我已经增加了堆大小,但这不是问题,因为我在某处遇到内存泄漏。

我找了解调试方法无济于事。我正在使用一个名为YouKit Java的工具来帮助我实现这个目标,并且我意识到使用过的堆内存会不断增长,直到它中断为止。 垃圾收集似乎随时都无法运行。

heap memory usage afer 16h 我已经运行了整个晚上的调试应用程序,即使最小也没有用,这种情况会发生:使用堆从几MB增加到XXXMB(在prod中大于1GB),根本没有负载。强制垃圾收集后,内存使用率恢复正常。

On the left the sudden decrease after I force GC. On the right, the memory couple of minutes after GC

下一张图显示了使用应用程序的基本用法强制GC之后再次使用的内存:页面重新加载,一些获取从db(sqlite)返回数据的查询以及一些写入db并打开一些套接字的查询。请注意,对于我测试的所有内容,我还运行相反的命令来取消我的更改。但记忆力不断增加。

我做了一个内存快照来浏览实例化的内容。最大的对象支配者显示对象 java.lang.ref.Finalizer 的巨大树状,知道我不会调用任何finalize方法(至少我不知道)

所以我很遗憾,Java不是我最大的优势,而且我很难调试这个。我想知道是否有可能阻止GC运行并造成这种情况? (正如我所看到的那样,在强制执行GC之后,事情会回归到更正常的状态)这可能是由TOMCAT或者球衣本身造成的吗?

关于应用程序的附注:它是一个API,允许您在后台(服务器和客户端套接字)中创建tcp隧道。每个隧道都是在一个线程中生成的。它还会执行一些数据获取和写入sqlite数据库。当工作完成时,我试图确保所有内容都正确关闭(数据库连接,查询,套接字和非引用...)。对于隧道,我依赖于一个名为javatunnel的库的轻微编辑版本(它可能也是罪魁祸首,但无法找到任何证明它的东西)

2 个答案:

答案 0 :(得分:0)

  

我意识到使用过的堆内存不断增长,直到   它打破了。垃圾收集似乎随时都无法运行。

在这种情况下,您应该查看JVM启动参数中的GC参数。 您的最大旧尺寸与最大新尺寸的比率是多少。如果最大旧尺寸与最大新尺寸相比太高,则您的对象将继续从幸存者移动到老一代并且不会被垃圾收集直到旧的尺寸达到阈值,这是我猜的>默认为75%。

所以,检查GC调整。这可能有所帮助。

答案 1 :(得分:0)

套接字可能未正确关闭,因此垃圾收集器无法释放它们和相关对象?我认为你应该尝试以这种方式深入研究。

您可以激活垃圾收集器日志以检测其运行时间。您必须在JVM启动时添加标志-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps