JAVAEE - 使用的堆内存继续增加,直到一切都崩溃
JAVAEE - Used heap memory just continue increasing until everything breaks
我正在 运行 在 tomcat 下安装一个中等大小的球衣网络应用程序。我发现由于内存不足问题,应用程序在执行一定时间后(几天)一直崩溃,我已经增加了堆大小,但这不是问题,因为我在某处面临内存泄漏。
我找了很多调试方法都没有用。我正在使用一个名为 YouKit Java 的工具来帮助我解决这个问题,我意识到使用的堆内存会无限增长,直到它崩溃。 垃圾回收似乎在任何时候都运行。
heap memory usage afer 16h
我整个晚上都有一个调试应用程序 运行,即使使用的很少甚至没有,也会发生这种情况:已用堆从几 MB 增长到 XXXMB(产品中 > 1GB),完全没有负载。强制垃圾回收后,内存使用恢复正常。
下一张图片显示了在我使用应用程序的基本用法强制 GC 后使用的内存再次增长:页面重新加载,一些查询 returns 来自 db (sqlite) 的数据,一些 post查询写入数据库并打开一些套接字。请注意,对于我测试的所有内容,我还 运行 应该取消我的更改的相反命令。但是内存一直在增加。
我做了一个内存快照来浏览实例化的内容。最大的对象-支配者显示对象 java.lang.ref.Finalizer 的巨大树状结构,知道我从来没有调用任何 finalize 方法(至少我不知道)
所以我对此很迷茫,Java 不是我最大的强项,我在调试它时遇到了很多困难。我想知道是否有什么可能阻止 GC 运行ning 并导致这种情况?
(正如我看到的那样,在强制执行 GC 之后事情会恢复到更正常的状态)这可能是由 TOMCAT 还是球衣本身引起的?
关于该应用程序的附注:它是一个 API,可让您在后台(服务器和客户端套接字)创建 tcp 隧道。每个隧道都在一个线程中产生。它还执行一些数据获取和写入 sqlite 数据库。当工作完成时,我试图确保一切都正确关闭(数据库连接、查询、套接字和未引用......)。对于隧道,我依赖于一个名为 javatunnel 的库的轻微编辑版本(它也可能是罪魁祸首,但找不到任何证明它的东西)
I realised that the used heap memory keeps growing indefinitly until
it breaks. The garbage collection doesnt seem to run at any moment.
在这种情况下,您应该查看 JVM 启动参数中的 GC 参数。
您的最大旧尺寸和最大新尺寸的比率是多少。如果最大旧大小与最大新大小相比太高,你的对象将继续从幸存者移动到老一代,并且不会被垃圾收集,直到老一代大小达到阈值,我猜默认情况下 > 75%。
所以,检查你的 GC 调优。可能会有帮助。
套接字可能没有正确关闭,以至于垃圾收集器无法释放它们和相关对象?我认为你应该尝试以这种方式进行更深入的调查。
您可以激活垃圾收集器日志来检测它何时运行。您必须在 JVM 启动时添加标志 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps
。
我正在 运行 在 tomcat 下安装一个中等大小的球衣网络应用程序。我发现由于内存不足问题,应用程序在执行一定时间后(几天)一直崩溃,我已经增加了堆大小,但这不是问题,因为我在某处面临内存泄漏。
我找了很多调试方法都没有用。我正在使用一个名为 YouKit Java 的工具来帮助我解决这个问题,我意识到使用的堆内存会无限增长,直到它崩溃。 垃圾回收似乎在任何时候都运行。
heap memory usage afer 16h 我整个晚上都有一个调试应用程序 运行,即使使用的很少甚至没有,也会发生这种情况:已用堆从几 MB 增长到 XXXMB(产品中 > 1GB),完全没有负载。强制垃圾回收后,内存使用恢复正常。
下一张图片显示了在我使用应用程序的基本用法强制 GC 后使用的内存再次增长:页面重新加载,一些查询 returns 来自 db (sqlite) 的数据,一些 post查询写入数据库并打开一些套接字。请注意,对于我测试的所有内容,我还 运行 应该取消我的更改的相反命令。但是内存一直在增加。
我做了一个内存快照来浏览实例化的内容。最大的对象-支配者显示对象 java.lang.ref.Finalizer 的巨大树状结构,知道我从来没有调用任何 finalize 方法(至少我不知道)
所以我对此很迷茫,Java 不是我最大的强项,我在调试它时遇到了很多困难。我想知道是否有什么可能阻止 GC 运行ning 并导致这种情况? (正如我看到的那样,在强制执行 GC 之后事情会恢复到更正常的状态)这可能是由 TOMCAT 还是球衣本身引起的?
关于该应用程序的附注:它是一个 API,可让您在后台(服务器和客户端套接字)创建 tcp 隧道。每个隧道都在一个线程中产生。它还执行一些数据获取和写入 sqlite 数据库。当工作完成时,我试图确保一切都正确关闭(数据库连接、查询、套接字和未引用......)。对于隧道,我依赖于一个名为 javatunnel 的库的轻微编辑版本(它也可能是罪魁祸首,但找不到任何证明它的东西)
I realised that the used heap memory keeps growing indefinitly until it breaks. The garbage collection doesnt seem to run at any moment.
在这种情况下,您应该查看 JVM 启动参数中的 GC 参数。 您的最大旧尺寸和最大新尺寸的比率是多少。如果最大旧大小与最大新大小相比太高,你的对象将继续从幸存者移动到老一代,并且不会被垃圾收集,直到老一代大小达到阈值,我猜默认情况下 > 75%。
所以,检查你的 GC 调优。可能会有帮助。
套接字可能没有正确关闭,以至于垃圾收集器无法释放它们和相关对象?我认为你应该尝试以这种方式进行更深入的调查。
您可以激活垃圾收集器日志来检测它何时运行。您必须在 JVM 启动时添加标志 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps
。