Расширение использования памяти резидентной памяти (RSS) Java-процесса

Наше недавнее наблюдение за нашей производственной системой говорит о том, что использование памяти резидентов нашего контейнера Java растет. Что касается этой проблемы, мы сделали некоторые исследования, чтобы понять, почему процесс Java потребляет гораздо больше памяти, чем кучи + потоки + общие объекты + кэш кода + и т.д., Используя некоторые собственные инструменты, такие как pmap. В результате этого мы обнаружили несколько 64M блоков памяти (попарно), выделенных собственным процессом (возможно, с malloc/mmap):

0000000000400000      4K r-x--  /usr/java/jdk1.7.0_17/bin/java
0000000000600000      4K rw---  /usr/java/jdk1.7.0_17/bin/java
0000000001d39000   4108K rw---    [ anon ]
0000000710000000  96000K rw---    [ anon ]
0000000715dc0000  39104K -----    [ anon ]
00000007183f0000 127040K rw---    [ anon ]
0000000720000000 3670016K rw---    [ anon ]
00007fe930000000  62876K rw---    [ anon ]
00007fe933d67000   2660K -----    [ anon ]
00007fe934000000  20232K rw---    [ anon ]
00007fe9353c2000  45304K -----    [ anon ]
00007fe938000000  65512K rw---    [ anon ]
00007fe93bffa000     24K -----    [ anon ]
00007fe940000000  65504K rw---    [ anon ]
00007fe943ff8000     32K -----    [ anon ]
00007fe948000000  61852K rw---    [ anon ]
00007fe94bc67000   3684K -----    [ anon ]
00007fe950000000  64428K rw---    [ anon ]
00007fe953eeb000   1108K -----    [ anon ]
00007fe958000000  42748K rw---    [ anon ]
00007fe95a9bf000  22788K -----    [ anon ]
00007fe960000000   8080K rw---    [ anon ]
00007fe9607e4000  57456K -----    [ anon ]
00007fe968000000  65536K rw---    [ anon ]
00007fe970000000  22388K rw---    [ anon ]
00007fe9715dd000  43148K -----    [ anon ]
00007fe978000000  60972K rw---    [ anon ]
00007fe97bb8b000   4564K -----    [ anon ]
00007fe980000000  65528K rw---    [ anon ]
00007fe983ffe000      8K -----    [ anon ]
00007fe988000000  14080K rw---    [ anon ]
00007fe988dc0000  51456K -----    [ anon ]
00007fe98c000000  12076K rw---    [ anon ]
00007fe98cbcb000  53460K -----    [ anon ]

Я интерпретирую строку с 0000000720000000 3670016K, ссылаясь на кучу пространства, размер которого мы определяем с использованием параметра JVM "-Xmx". Сразу после этого начинаются пары, из которых сумма равна 64M. Мы используем 64-разрядную архитектуру CentOS версии 5.10 (Final) и JDK 1.7.0_17.

Вопрос в том, каковы эти блоки? Какая подсистема выделяет их?

Обновление: мы не используем JIT-код и/или JNI-код.

Ответ 1

Я столкнулся с той же проблемой. Это известная проблема с glibc >= 2.10

Исключение состоит в том, чтобы установить эту переменную env export MALLOC_ARENA_MAX=4

Статья IBM о настройке MALLOC_ARENA_MAX https://www.ibm.com/developerworks/community/blogs/kevgrig/entry/linux_glibc_2_10_rhel_6_malloc_may_show_excessive_virtual_memory_usage?lang=en

Google для MALLOC_ARENA_MAX или найдите его на SO, чтобы найти много ссылок.

Возможно, вы захотите настроить также другие параметры malloc для оптимизации для низкой фрагментации выделенной памяти:

# tune glibc memory allocation, optimize for low fragmentation
# limit the number of arenas
export MALLOC_ARENA_MAX=2
# disable dynamic mmap threshold, see M_MMAP_THRESHOLD in "man mallopt"
export MALLOC_MMAP_THRESHOLD_=131072
export MALLOC_TRIM_THRESHOLD_=131072
export MALLOC_TOP_PAD_=131072
export MALLOC_MMAP_MAX_=65536

Ответ 2

Также возможно, что существует утечка памяти. Общей проблемой является утечка встроенной памяти, вызванная не закрытием ZipInputStream/GZIPInputStream.

Типичным способом открытия ZipInputStream является вызов Class.getResource/ClassLoader.getResource и вызов openConnection().getInputStream() в экземпляре java.net.URL или вызов Class.getResourceAsStream/ClassLoader.getResourceAsStream. Нужно обеспечить, чтобы эти потоки всегда закрывались.

Вы можете использовать jemalloc для отладки утечек памяти, включив профилирование профилей malloc, указав параметры в переменной среды MALLOC_CONF. Подробные инструкции доступны в этом блоге: http://www.evanjones.ca/java-native-leak-bug.html. В этом сообщении в блоге также есть информация об использовании jemalloc для отладки утечки собственной памяти в Java-приложениях.

В том же блоге также содержится информация о другой утечке памяти, связанной с ByteBuffers.