Java进程内存无限增长。内存泄漏?
Java进程内存无限增长。内存泄漏?
我们在Solaris 10上运行了一个Java进程,为约200-300个并发用户提供服务。管理员报告说,随着时间的推移,进程使用的内存显著增加。它在几天内达到2GB,并且不断增长。
我们已经转储了堆并使用Eclipse Memory Profiler进行了分析,但在那里我们无法看到任何异样的东西。堆大小非常小。
在向我们的应用程序添加内存统计日志后,我们发现“top”实用程序报告的内存使用情况与MemoryMXBean和Runtime库报告的使用情况存在差异。
这里是两者的输出。
Memory usage information From the Runtime library Free memory: 381MB Allocated memory: 74MB Max memory: 456MB Total free memory: 381MB From the MemoryMXBean library. Heap Committed: 136MB Heap Init: 64MB Heap Used: 74MB Heap Max: 456MB Non Heap Committed: 73MB Non Heap Init: 4MB Non Heap Used: 72MB Current idle threads: 4 Current total threads: 13 Current busy threads: 9 Current queue size: 0 Max threads: 200 Min threads: 8 Idle Timeout: 60000 PID USERNAME NLWP PRI NICE SIZE RES STATE TIME CPU COMMAND 99802 axuser 115 59 0 2037M 1471M sleep 503:46 0.14% java
这怎么可能? top命令报告了更多的使用情况。我期望RES应该接近堆+非堆。
但是,pmap-x 报告了大部分内存在堆中:
Address Kbytes RSS Anon Locked Mode Mapped File *102000 56 56 56 - rwx---- [ heap ] *110000 3008 3008 2752 - rwx---- [ heap ] *400000 1622016 1621056 1167568 - rwx---- [ heap ] *000000 45056 45056 45056 - rw----- [ anon ]
有没有人能给点提示?我彻底迷失了。
谢谢。
更新
在Linux上似乎没有这个问题。
此外,根据Peter Lawrey的回复,pmap报告的“堆”是本地堆,而不是Java堆。
我遇到了类似的问题并找到了一个解决方法:
Solaris 11 JDK10 REST application using HTTPS (jetty server) There was a significant increase of c-heap (observed via pmap) over time
我决定使用libumem进行一些压力测试。
所以我使用以下命令启动进程:
UMEM_DEBUG=default UMEM_LOGGING=transaction LD_PRELOAD=libumem.so.1
然后用https请求对应用程序进行了压力测试。
一段时间后,我用mdb连接到了进程。
在mdb中,我使用了命令::findleaks,并且它显示这个是一个泄漏:
libucrypto.so.1`ucrypto_digest_init
因此,似乎Java加密体系结构(JCA)实现OracleUcrypto在Solaris上存在一些问题。
问题通过更新$JAVA_HOME/conf/security/java.security文件来解决 -
我将OracleUcrypto的优先级更改为3,将SUN的实现更改为1
security.provider.3=OracleUcrypto security.provider.2=SunPKCS11 ${java.home}/conf/security/sunpkcs11-solaris.cfg security.provider.1=SUN
之后,问题就消失了。
这也解释了为什么在Linux上没有问题 - 因为存在不同的JCA提供程序实现