2014-09-25 12 views
7

La nostra recente osservazione sul nostro sistema di produzione ci dice che l'utilizzo della memoria residente del nostro contenitore Java cresce. Riguardo a questo problema, abbiamo fatto alcune indagini per capire perché il processo java consuma molta più memoria di Heap + Thread Stacks + Oggetti condivisi + Code Cache + etc, usando alcuni strumenti nativi come pmap. Come risultato di ciò, abbiamo trovato alcuni blocchi di memoria 64M (a coppie) assegnate dal processo nativo (probabilmente con malloc/mmap):Utilizzo in memoria residente crescente (RSS) di Java Process

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 ] 

interpreto la linea con 0.000.000,72 miliardi 3670016K si riferisce allo spazio mucchio, di cui le dimensioni che definiamo utilizzando il parametro JVM "-Xmx". Subito dopo, iniziano le coppie, di cui la somma è esattamente 64M. Stiamo usando CentOS versione 5.10 (finale) arch a 64 bit e JDK 1.7.0_17.

La domanda è: quali sono quei blocchi? Quale sottosistema li assegna?

Aggiornamento: non vengono utilizzate chiamate di codice nativo JIT e/o JNI.

+0

Hai profilato la tua applicazione java con VisualVM o simile? –

+0

Con VisualVM, è possibile monitorare solo all'interno dello spazio heap. –

risposta

10

Mi sono imbattuto nello stesso problema. Questo è un problema noto con glibc> = 2.10

La cura è di impostare questa variabile ENV export MALLOC_ARENA_MAX=4

articolo IBM sull'impostazione 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 per MALLOC_ARENA_MAX o cercarlo sul SO per trovare un sacco di riferimenti.

si potrebbe desiderare di mettere a punto anche altre opzioni per ottimizzare malloc per la bassa frammentazione di memoria allocata:

# 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

Questo è stato il modo in cui abbiamo risolto il problema. Grazie per la tua risposta. –

+3

C'è un bug JVM in Java 8, che si traduce in una crescita della memoria nativa illimitata: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8164293 - Se questo ti interessa, usa 'MALLOC_ARENA_MAX' può rallentare la crescita della memoria, ma non risolvere completamente il problema. – outofcoffee

2

E 'anche possibile che ci sia una perdita di memoria nativa. Un problema comune è la perdita di memoria nativa causata dalla mancata chiusura di ZipInputStream/GZIPInputStream.

Un tipico modo che un ZipInputStream viene aperto è di una chiamata a Class.getResource/ClassLoader.getResource e chiamando openConnection().getInputStream() nell'istanza java.net.URL o chiamando Class.getResourceAsStream/ClassLoader.getResourceAsStream. Bisogna assicurarsi che questi flussi vengano sempre chiusi.

È possibile utilizzare jemalloc per eseguire il debug di perdite di memoria native attivando il profilo di campionamento malloc specificando le impostazioni nella variabile di ambiente MALLOC_CONF. Istruzioni dettagliate sono disponibili in questo post del blog: http://www.evanjones.ca/java-native-leak-bug.html. This blog post ha anche informazioni sull'utilizzo di jemalloc per eseguire il debug di una perdita di memoria nativa nelle applicazioni java.

Lo stesso blog contiene anche informazioni su un altro native memory leak related to ByteBuffers.

+0

Questa discussione riguarda la crescita della dimensione RSS del processo Java su CloudFoundry: https://github.com/cloudfoundry/java-buildpack/issues/320#issuecomment-242350879 –

Problemi correlati