我们在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堆。
答案 0 :(得分:1)
在垃圾收集环境中,保留未使用的指针相当于“无法泄漏”并阻止GC执行其工作。这真的很容易 不小心保持指针。
常见的罪魁祸首是哈希表。另一种是阵列或载体 逻辑清除(通过将重用索引设置为0)但实际的位置 数组的内容(在使用索引之上)仍然指向某个东西。
答案 1 :(得分:0)
我遇到了类似的问题并找到了解决方法:
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 =默认UMEM_LOGGING =事务LD_PRELOAD = libumem.so.1
并通过https请求强调了该应用程序。 一段时间后,我使用mdb连接到该进程。 在mdb中,我使用了::: findleaks命令,并将其显示为泄漏:
libucrypto.so.1`ucrypto_digest_init
因此,似乎JCA(Java密码体系结构)实现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提供程序的实现方式不同