Java - слишком высокая внутренняя память - PullRequest
0 голосов
/ 07 марта 2019

Что такое внутренняя собственная память в 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, поэтому я добавил в systemctl приложения

Environment="MALLOC_ARENA_MAX=2"

Также я попробовал 4.

Моя версия GLIBC: ldd (Debian GLIBC 2.24-11 + deb9u3) 2.24

Я использую сервер Debian 9 x64 (обновленный) с 24 потоками, 24 ГБ ОЗУ. Разумеется, предназначено только для этого программного обеспечения, и нет никаких других приложений. Я сделал heapdump (при использовании ~ 22 ГБ) и в обзоре анализатора памяти Eclipse я вижу:

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

У вас есть идея, как проверить, что находится внутри этой внутренней памяти, или как я могу ограничить использование? Мое приложение все время зависает, когда память заканчивается, но процесс Java все еще работает. Просто не работает, но процесс все еще существует.

1 Ответ

0 голосов
/ 08 марта 2019

Вы работаете в 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

(или обобщить / list /показывать вместо подсчета, но обычно после "перенаправления на")

...