2014-09-25 16 views
7

Nasza niedawna obserwacja naszego systemu produkcyjnego mówi nam, że zużycie pamięci rezydentnej naszego kontenera Java rośnie. Odnośnie tego problemu, podjęliśmy pewne badania, aby zrozumieć, dlaczego proces java zużywa znacznie więcej pamięci niż stos Heap + stosy wątków + współdzielone obiekty + pamięć podręczna kodu + itd., Używając niektórych narzędzi natywnych, takich jak pmap. W wyniku tego, znaleźliśmy kilka bloków pamięci 64M (w parach) przydzielonych przez proces natywny (prawdopodobnie z malloc/mmap):Rosnące wykorzystanie pamięci rezydentnej (RSS) procesu Java

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 ] 

interpretować linia z 0000000720000000 3670016K odnosi się do przestrzeni, kupa, z których rozmiar definiujemy za pomocą parametru JVM "-Xmx". Zaraz potem zaczynają się pary, których suma wynosi dokładnie 64M. Używamy oprogramowania CentOS Release 5.10 (Final) 64-bit arch i JDK 1.7.0_17.

Pytanie brzmi, jakie są te bloki? Który podsystem je przydziela?

Aktualizacja: Nie używamy inwokacji kodu natywnego JIT i/lub JNI.

+0

Czy profilowałeś swoją aplikację java za pomocą VisualVM lub podobnego? –

+0

Z VisualVM można monitorować tylko w obszarze sterty. –

Odpowiedz

10

Wpadłem na ten sam problem. Jest to znany problem z glibc> = 2,10

Lekarstwo jest ustawienie tej zmiennej ENV export MALLOC_ARENA_MAX=4

IBM artykuł o ustawianiu 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 dla MALLOC_ARENA_MAX lub poszukać go na SO znaleźć wiele referencji.

może chcesz oglądać także inne opcje malloc w celu optymalizacji dla małej fragmentacji przydzielonej pamięci:

# 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 
+0

W ten sposób rozwiązaliśmy porblem. Thx za twoją odpowiedź. –

+3

Występuje błąd JVM w Java 8, który powoduje wzrost nieograniczonej pamięci natywnej: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8164293 - Jeśli to dotyczy Ciebie, użyj 'MALLOC_ARENA_MAX' może spowolnić wzrost pamięci, ale nie rozwiązuje całkowicie problemu. – outofcoffee

2

Możliwe jest również, że nie jest rodowitym wyciek pamięci. Typowym problemem są wycieki z pamięci rodzimej spowodowane niezamknięciem.

Typowy sposób, że ZipInputStream jest otwierany jest przez wywołanie Class.getResource/ClassLoader.getResource i wywołanie openConnection().getInputStream() na przykład java.net.URL lub dzwoniąc Class.getResourceAsStream/ClassLoader.getResourceAsStream. Trzeba upewnić się, że strumienie te są zawsze zamknięte.

Można użyć jemalloc do debugowania wycieków natywnej pamięci, włączając profilowanie próbkowania malloc, określając ustawienia zmiennej środowiskowej MALLOC_CONF. Szczegółowe instrukcje są dostępne w tym poście na blogu: http://www.evanjones.ca/java-native-leak-bug.html. This blog post posiada również informacje o używaniu jemalloc do debugowania wycieku pamięci natywnej w aplikacjach java.

Ten sam blog zawiera również informacje o innym native memory leak related to ByteBuffers.

+0

Ta dyskusja dotyczy wzrostu rozmiaru kanału Java w procesie Java na CloudFoundry: https://github.com/cloudfoundry/java-buildpack/issues/320#issuecomment-242350879 –

Powiązane problemy