Java-内部本机内存使用率过高

时间:2019-03-07 19:00:16

标签: java memory memory-leaks out-of-memory

什么是Java中的内部本机内存,如何限制它? 我正在使用一种流行的Java应用程序之一,例如tomcat,但是几个小时后我的内存使用率很高。

我尝试检测出问题所在,然后检查了JCMD:

Total: reserved=20207MB, committed=18968MB
-                 Java Heap (reserved=10000MB, committed=10000MB)
                            (mmap: reserved=10000MB, committed=10000MB)

-                     Class (reserved=1069MB, committed=50MB)
                            (classes #6159)
                            (malloc=1MB #19368)
                            (mmap: reserved=1068MB, committed=48MB)

-                    Thread (reserved=570MB, committed=570MB)
                            (thread #2039)
                            (stack: reserved=561MB, committed=561MB)
                            (malloc=7MB #10216)
                            (arena=3MB #4076)

-                      Code (reserved=252MB, committed=52MB)
                            (malloc=8MB #10918)
                            (mmap: reserved=244MB, committed=44MB)

-                        GC (reserved=553MB, committed=553MB)
                            (malloc=150MB #129854)
                            (mmap: reserved=403MB, committed=403MB)

-                  Compiler (reserved=2MB, committed=2MB)
                            (malloc=2MB #2346)

-                  Internal (reserved=7726MB, committed=7726MB)
                            (malloc=7726MB #67913)

-                    Symbol (reserved=10MB, committed=10MB)
                            (malloc=8MB #67876)
                            (arena=2MB #1)

-    Native Memory Tracking (reserved=5MB, committed=5MB)
                            (malloc=1MB #7514)
                            (tracking overhead=5MB)

-                   Unknown (reserved=20MB, committed=0MB)
                            (mmap: reserved=20MB, committed=0MB)

开始时的内存使用情况如下:

Total: reserved=14324MB, committed=12096MB
-                 Java Heap (reserved=10000MB, committed=9050MB)
                            (mmap: reserved=10000MB, committed=9050MB)

-                     Class (reserved=1069MB, committed=49MB)
                            (classes #6130)
                            (malloc=1MB #16522)
                            (mmap: reserved=1068MB, committed=48MB)

-                    Thread (reserved=400MB, committed=400MB)
                            (thread #1381)
                            (stack: reserved=394MB, committed=394MB)
                            (malloc=4MB #6926)
                            (arena=2MB #2760)

-                      Code (reserved=251MB, committed=48MB)
                            (malloc=8MB #10237)
                            (mmap: reserved=244MB, committed=41MB)

-                        GC (reserved=501MB, committed=466MB)
                            (malloc=98MB #103127)
                            (mmap: reserved=403MB, committed=368MB)

-                  Compiler (reserved=1MB, committed=1MB)
                            (malloc=1MB #1142)

-                  Internal (reserved=2068MB, committed=2068MB)
                            (malloc=2068MB #49248)

-                    Symbol (reserved=9MB, committed=9MB)
                            (malloc=7MB #67619)
                            (arena=2MB #1)

-    Native Memory Tracking (reserved=5MB, committed=5MB)
                            (tracking overhead=4MB)

-                   Unknown (reserved=20MB, committed=0MB)
                            (mmap: reserved=20MB, committed=0MB)

我认为这可能是应用程序中的内存泄漏,但是堆大小可能会导致高使用率。 另外,我在glibc中找不到有关bug的文章,因此我已将其添加到应用程序的systemctl

Environment="MALLOC_ARENA_MAX=2"

我也尝试过4。

我的GLIBC版本是:ldd(Debian GLIBC 2.24-11 + deb9u3)2.24

我正在使用具有24个线程,24GB RAM的服务器Debian 9 x64(更新)。当然仅专用于此软件,没有任何其他应用程序。 我做了heapdump(使用量约为22gb),在Eclipse内存分析器概述中,我看到了:

Size: 2,3 GB Classes: 6,3k Objects: 2,3m Class Loader: 23

您有什么想法,如何检查内部存储器中的内容,或者如何限制使用量? 当内存用完了,但是Java进程仍在运行时,我的应用程序一直处于阻塞状态。只是不起作用,但是过程仍然存在。

1 个答案:

答案 0 :(得分:0)

您是否正在Linux上运行?如果是这样,请抓住程序的实时核心(使用gcore),然后使用https://github.com/vmware/chap

查看该核心。

以下命令可能会有用:

count writable
count rxonly
count readonly
count inaccessible
summarize writable
summarize rxonly
summarize readonly
summarize inaccessible

鉴于您使用的线程数量较多,还应该尝试:

count stacks

这将向您显示与线程有效关联(而不是缓存)的堆栈正在使用多少内存。

如果数量很多,您可以使用以下方法确定通常浪费了多少堆栈:

redirect on
describe stacks

如果堆栈比所需的大得多,则可以使用“ ulimit -s”来设置最大堆栈大小(在启动该过程的某些脚本中)以对其进行修剪。

如果您想了解本机代码使用的内存,请尝试:

count allocated
count used
count free

(或汇总/列出/显示而不是计数,但通常在“重定向到”之后)