什么是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的文章,所以我已添加到app的systemctl
Environment="MALLOC_ARENA_MAX=2"
另外,我试过4。
我的GLIBC版本是:ldd(Debian GLIBC 2.24-11 + deb9u3)2.24
我使用服务器Debian 9 x64(更新)24线程,24GB RAM。当然只专用于这个软件,并没有任何其他应用程序。我做了heapdump,(当使用率是~22gb时),在Eclipse内存分析器概述中,我看到:
Size: 2,3 GB Classes: 6,3k Objects: 2,3m Class Loader: 23
你有什么想法,如何检查这个内部存储器内的内容,或者我如何限制使用?当内存结束时,我的应用程序始终处于停滞状态,但java进程仍在运行。只是不工作,但过程仍然存在。
你在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
(或总结/列表/显示而非计数,但通常在“重定向”之后)