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

JAVAEE使用的堆内存会继续增加,直到一切都中断,java,memory,garbage-collection,resource-leak,Java,Memory,Garbage Collection,Resource Leak,我在tomcat下运行一个中等大小的jersey web应用程序。我发现应用程序在执行一定时间后(几天)由于内存不足而不断崩溃,我已经增加了堆大小,但这不是问题所在,因为我在某处面临内存泄漏 我找了一些方法来调试它,但没有用。我正在使用一个名为YouKit Java的工具来帮助我实现这一点,我意识到使用的堆内存一直在不确定地增长,直到崩溃垃圾收集似乎在任何时候都不会运行。 我整晚都在运行一个调试应用程序,即使使用很少或没有使用,这种情况也会发生:使用的堆从几MB增长到XXXMB(prod中大于

我在tomcat下运行一个中等大小的jersey web应用程序。我发现应用程序在执行一定时间后(几天)由于内存不足而不断崩溃,我已经增加了堆大小,但这不是问题所在,因为我在某处面临内存泄漏

我找了一些方法来调试它,但没有用。我正在使用一个名为YouKit Java的工具来帮助我实现这一点,我意识到使用的堆内存一直在不确定地增长,直到崩溃垃圾收集似乎在任何时候都不会运行。

我整晚都在运行一个调试应用程序,即使使用很少或没有使用,这种情况也会发生:使用的堆从几MB增长到XXXMB(prod中大于1GB),根本没有任何负载。强制垃圾收集后,内存使用恢复正常

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

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

所以我对此非常迷茫,Java并不是我最大的优势,我在调试它时遇到了很多困难。我想知道是否有什么可能阻止GC运行并导致这种情况? (正如我看到的,在强制执行GC之后,事情会回到更正常的状态)这是由TOMCAT还是jersey本身造成的

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

我意识到使用的堆内存一直在不确定地增长,直到 它坏了。垃圾收集似乎在任何时候都不会运行

在本例中,您应该查看JVM启动参数中的GC参数。 您的最大旧尺码和最大新尺码的比例是多少。如果“最大旧大小”与“最大新大小”相比太高,则您的对象将继续从幸存者移动到旧代,并且在旧代大小达到阈值(默认值为>75%)之前不会进行垃圾收集


所以,请检查GC调优。这可能会有所帮助。

套接字可能未正确关闭,因此垃圾收集器无法释放它们和相关对象?我认为你应该试着用这种方式进行更深入的调查


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

运行jconsole并检查应用程序中是否存在内存泄漏。具有finalize方法的每个对象都将由Finalizer最终确定。任何具有终结器方法的垃圾对象都将首先连接到终结器。您可以通过终结器检查连接的对象。