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

33 浏览
0 Comments

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堆。

admin 更改状态以发布 2023年5月21日
0
0 Comments

\n\n\n在垃圾回收的环境下,持有未使用的指针相当于“未泄漏”,这会阻止GC执行其工作。 在意外情况下保留指针非常容易。\n\n常见的罪魁祸首是哈希表。 另一个罪魁祸首是逻辑上已清除的数组或向量(通过将重用索引设置为0),但是数组的实际内容(在使用索引之上)仍在指向某些内容。

0
0 Comments

我遇到了类似的问题并找到了一个解决方法:

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提供程序实现

0