Java进程内存无限增长。内存泄漏?

时间:2016-03-23 18:12:33

标签: java memory heap

我们在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堆。

2 个答案:

答案 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提供程序的实现方式不同