java 服务器有 jetty 内存泄漏问题
java server with jetty memory leak issue
我运行在这个应用程序中嵌入了 Jetty 服务器。尽管堆大小根本没有改变,但应用程序正在慢慢消耗更多内存。
这是启动应用程序的命令:
java -server -Xms1G -Xmx1G -Dfile.encoding=UTF-8
这是新遗迹的图表,内存使用量增加
它开始使用 1140MB,8 小时后使用 1290MB
这是堆的jvisualvm图表。
有什么建议吗?
[编辑1]
添加转储 https://www.dropbox.com/s/1gt1i9dhjtjauf0/gameserver-20160226-2107.zip?dl=0
[编辑2]
这是我当前调查的一些笔记
=如何监控堆外内存
添加参数
-XX:NativeMemoryTracking=detail -XX:+UnlockDiagnosticVMOptions -XX:+PrintNMTStatistics
运行命令
jcmd 3322 VM.native_memory 摘要
@see https://devcenter.heroku.com/articles/java-memory-issues
= 检查默认线程堆栈大小
java-XX:+PrintFlagsFinal-版本| grep ThreadStackSize
intx ThreadStackSize = 1024
How to reclaim the memory used by a Java thread stack?
=了解最大内存
最大内存 = [-Xmx] + [-XX:MaxPermSize] + number_of_threads * [-Xss]
@see https://plumbr.eu/blog/memory-leaks/why-does-my-java-process-consume-more-memory-than-xmx
= 动作
减少线程堆栈的大小。 (理论上,你可以低至64K ...)
-XX:ThreadStackSize=256
降低 GC 后堆空闲的最小百分比以避免扩展。
-XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=10
现在会继续监测...
经过大量不同类型的调查,我回到 Eclipse Memory analyzer 并再次尝试......
但这次我决定相信泄漏报告说:
One instance of "org.hibernate.internal.SessionFactoryImpl" loaded by
"sun.misc.Launcher$AppClassLoader @ 0xc001d4f8" occupies 2.956.808
(21,05%) bytes. The memory is accumulated in one instance of
"org.hibernate.internal.SessionFactoryImpl" loaded by
"sun.misc.Launcher$AppClassLoader @ 0xc001d4f8".
然后我将调查转移到我的 DAO 实现上,预计我忘记关闭一个或其他 EntityManager 调用。事实并非如此,所有这些都是在使用后调用一个很好的 close() 方法。
然后我意识到问题可能出在休眠本身上,因为有问题的对象是 SessionFactoryImpl,所以我更改了我的 DAO 实现以每次清除 Hibernate 一级缓存创建实体管理器,因为我找不到禁用它的方法。
一天结束的结果 = 成功了!! :) 内存稍有变化,几分钟后恢复,但不要再以疯狂的方式增长(24 小时内增加 1000MB)。
这是我修改的代码,希望对大家有帮助。
public EntityManager getEntityManager(){
if( emf == null ){
if (parameters == null) {
emf = Persistence.createEntityManagerFactory(persistenceUnitName);
} else {
emf = Persistence.createEntityManagerFactory(persistenceUnitName, parameters);
}
} else {
emf.getCache().evictAll();
}
EntityManager em = emf.createEntityManager();
return em;
}
关键在这里:emf.getCache().evictAll();
我运行在这个应用程序中嵌入了 Jetty 服务器。尽管堆大小根本没有改变,但应用程序正在慢慢消耗更多内存。
这是启动应用程序的命令:
java -server -Xms1G -Xmx1G -Dfile.encoding=UTF-8
这是新遗迹的图表,内存使用量增加
这是堆的jvisualvm图表。
有什么建议吗?
[编辑1] 添加转储 https://www.dropbox.com/s/1gt1i9dhjtjauf0/gameserver-20160226-2107.zip?dl=0
[编辑2] 这是我当前调查的一些笔记
=如何监控堆外内存 添加参数
-XX:NativeMemoryTracking=detail -XX:+UnlockDiagnosticVMOptions -XX:+PrintNMTStatistics
运行命令 jcmd 3322 VM.native_memory 摘要 @see https://devcenter.heroku.com/articles/java-memory-issues
= 检查默认线程堆栈大小 java-XX:+PrintFlagsFinal-版本| grep ThreadStackSize
intx ThreadStackSize = 1024
How to reclaim the memory used by a Java thread stack?
=了解最大内存 最大内存 = [-Xmx] + [-XX:MaxPermSize] + number_of_threads * [-Xss] @see https://plumbr.eu/blog/memory-leaks/why-does-my-java-process-consume-more-memory-than-xmx
= 动作 减少线程堆栈的大小。 (理论上,你可以低至64K ...)
-XX:ThreadStackSize=256
降低 GC 后堆空闲的最小百分比以避免扩展。
-XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=10
现在会继续监测...
经过大量不同类型的调查,我回到 Eclipse Memory analyzer 并再次尝试......
但这次我决定相信泄漏报告说:
One instance of "org.hibernate.internal.SessionFactoryImpl" loaded by "sun.misc.Launcher$AppClassLoader @ 0xc001d4f8" occupies 2.956.808 (21,05%) bytes. The memory is accumulated in one instance of "org.hibernate.internal.SessionFactoryImpl" loaded by "sun.misc.Launcher$AppClassLoader @ 0xc001d4f8".
然后我将调查转移到我的 DAO 实现上,预计我忘记关闭一个或其他 EntityManager 调用。事实并非如此,所有这些都是在使用后调用一个很好的 close() 方法。
然后我意识到问题可能出在休眠本身上,因为有问题的对象是 SessionFactoryImpl,所以我更改了我的 DAO 实现以每次清除 Hibernate 一级缓存创建实体管理器,因为我找不到禁用它的方法。
一天结束的结果 = 成功了!! :) 内存稍有变化,几分钟后恢复,但不要再以疯狂的方式增长(24 小时内增加 1000MB)。
这是我修改的代码,希望对大家有帮助。
public EntityManager getEntityManager(){
if( emf == null ){
if (parameters == null) {
emf = Persistence.createEntityManagerFactory(persistenceUnitName);
} else {
emf = Persistence.createEntityManagerFactory(persistenceUnitName, parameters);
}
} else {
emf.getCache().evictAll();
}
EntityManager em = emf.createEntityManager();
return em;
}
关键在这里:emf.getCache().evictAll();