2015-07-01 18 views
17

Quando si esegue un'app Java (in YARN) con il rilevamento memoria nativa abilitato (-XX:NativeMemoryTracking=detail, vedere https://docs.oracle.com/javase/8/docs/technotes/guides/vm/nmt-8.html e https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr007.html), è possibile visualizzare la quantità di memoria utilizzata dalla JVM in diverse categorie.Perché una JVM segnala più memoria impegnata rispetto alla dimensione impostata residente del processo linux?

mia app JDK 1.8.0_45 spettacoli:

 
Native Memory Tracking: 

Total: reserved=4023326KB, committed=2762382KB 
-     Java Heap (reserved=1331200KB, committed=1331200KB) 
          (mmap: reserved=1331200KB, committed=1331200KB) 

-      Class (reserved=1108143KB, committed=64559KB) 
          (classes #8621) 
          (malloc=6319KB #17371) 
          (mmap: reserved=1101824KB, committed=58240KB) 

-     Thread (reserved=1190668KB, committed=1190668KB) 
          (thread #1154) 
          (stack: reserved=1185284KB, committed=1185284KB) 
          (malloc=3809KB #5771) 
          (arena=1575KB #2306) 

-      Code (reserved=255744KB, committed=38384KB) 
          (malloc=6144KB #8858) 
          (mmap: reserved=249600KB, committed=32240KB) 

-      GC (reserved=54995KB, committed=54995KB) 
          (malloc=5775KB #217) 
          (mmap: reserved=49220KB, committed=49220KB) 

-     Compiler (reserved=267KB, committed=267KB) 
          (malloc=137KB #333) 
          (arena=131KB #3) 

-     Internal (reserved=65106KB, committed=65106KB) 
          (malloc=65074KB #29652) 
          (mmap: reserved=32KB, committed=32KB) 

-     Symbol (reserved=13622KB, committed=13622KB) 
          (malloc=12016KB #128199) 
          (arena=1606KB #1) 

- Native Memory Tracking (reserved=3361KB, committed=3361KB) 
          (malloc=287KB #3994) 
          (tracking overhead=3075KB) 

-    Arena Chunk (reserved=220KB, committed=220KB) 
          (malloc=220KB) 

Questo dimostra 2.7GB di memoria impegnata, tra 1,3 GB di heap allocata e quasi 1,2 GB di stack di thread allocati (usando molti fili).

Tuttavia, quando è in esecuzione ps ax -o pid,rss | grep <mypid> o top mostra solo 1,6 GB di memoria residente RES/rss. Controllo di swap dice che nessuno è in uso:

 
free -m 
      total  used  free  shared buffers  cached 
Mem:  129180  99348  29831   0  2689  73024 
-/+ buffers/cache:  23633  105546 
Swap:  15624   0  15624 

Perché la JVM indicano la memoria 2.7GB viene commesso quando solo 1,6 GB di residenza? Dove sono finiti gli altri?

+0

possibile duplicato di [Le tracce RSS sono riservate o memorizzate?] (Http://stackoverflow.com/questions/31071019/does-rss-tracks-reserved-or-commited-memory) – the8472

+0

no. questa domanda e risposta trattano la memoria riservata ma non impegnata, oltre a dire che la differenza tra lo scambio commesso e quello residente è che non ho notato il caso qui. –

+0

la risposta copre anche le differenze tra commesso e residente. – the8472

risposta

17

Sto iniziando a sospettare che la memoria dello stack (a differenza dell'heap JVM) sembra essere precommessa senza diventare residente e nel tempo diventa residente solo fino al limite massimo dell'utilizzo effettivo dello stack.

Sì, malloc/mmap è pigro se non indicato diversamente. Le pagine sono supportate solo dalla memoria fisica dopo l'accesso.

La memoria heap del GC viene effettivamente toccata dal raccoglitore di copie o dal pre-azzeramento (-XX:+AlwaysPreTouch), quindi sarà sempre residente. Le pile di thread otoh non sono interessate da questo.

Per ulteriore conferma è possibile utilizzare pmap -x <java pid> e fare riferimento incrociato all'RSS di vari intervalli di indirizzi con l'uscita dalla mappa della memoria virtuale da NMT.


La memoria riservata è stata salvata con PROT_NONE. Ciò significa che gli intervalli di spazio di indirizzi virtuali hanno voci nelle strutture vma del kernel e quindi non saranno utilizzati da altre chiamate mmap/malloc. Ma continueranno a causare errori di pagina inoltrati al processo come SIGSEGV, ovvero accedervi è un errore.

È importante disporre di intervalli di indirizzi contigui disponibili per uso futuro, che a loro volta semplificano l'aritmetica del puntatore.

La memoria con memoria non vincolata ma non memorizzata è stata mappata con - ad esempio - PROT_READ | PROT_WRITE ma l'accesso continua a causare un errore di pagina. Ma quell'errore di pagina viene gestito silenziosamente dal kernel eseguendolo con la memoria effettiva e ritornando all'esecuzione come se nulla fosse accaduto.
I.e. è un dettaglio/ottimizzazione dell'implementazione che non verrà notato dal processo stesso.


fornire una ripartizione dei concetti:

Usato Heap: la quantità di memoria occupata da oggetti in tempo reale secondo l'ultimo GC

commessi: gli intervalli di indirizzi che sono stati mappato con qualcosa di diverso da PROT_NONE.Possono o non possono essere supportati da fisici o swap a causa di allocazioni pigre e paging.

Riservato: l'intervallo di indirizzi totale che è stato pre-mappato tramite mmap per un particolare pool di memoria.
Il riservati - commesso differenza consiste di PROT_NONE mappature, che sono garantiti per non essere sostenuta da memoria fisica

Resident: Pagine che sono attualmente in RAM fisica. Ciò significa codice, stack, parte dei pool di memoria impegnati, ma anche porzioni di file mmaped che sono stati recentemente consultati e allocazioni al di fuori del controllo della JVM.

Virtual: la somma di tutti i mapping di indirizzi virtuali. Copertine impegnate, pool di memoria riservati ma anche file mappati o memoria condivisa. Questo numero è raramente informativo in quanto la JVM può riservare in anticipo intervalli di indirizzi molto ampi o file grandi di mmap.

+0

Confermato tramite pmap -x che il thread varia come indicato da dettaglio NMT typcial ha solo RSS di 88 su 1028 o giù di lì. Grazie per il consiglio. Puoi spiegare cosa significa realmente impegnato, e in che modo è diverso da riservato se entrambi possono riferirsi alla memoria virtuale che non è ancora residente/utilizzata? –

+0

aggiornato la mia risposta – the8472

+0

Grazie! Molto utile. Sarebbe fantastico se il tracciamento della memoria nativa JVM verificasse effettivamente i dati eseguiti da pmap -x e mostrasse ciò che era effettivamente residente. –

Problemi correlati