2013-07-15 6 views
8

Eseguire un codice molto semplice per provare a vedere come funzionano i garbage collector.Comportamento GC inatteso: alcuni dati vanno sempre nella generazione di possesso

String a = null; 
while (true) { 
    a = new String(" no... "); 
} 

Sto usando ParallelGC. Ho stampato i risultati GC e qui sono i primi (minori) GC.

[GC [PSYoungGen: 16448K->1616K(19136K)] 16448K->1624K(62848K), 0.0022134 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 

youngGen scese da 14880K tuttavia fullHeap è sceso di appena 14872K

Questo significa 8k si è trasferito alla generazione mandato? La mia comprensione è che il GC potrebbe essere stato definito come un istanza della classe 'a' che deve essere stato contrassegnato come vivo e spostato alla generazione di possesso. Questa comprensione è corretta? Inoltre, è questo "Floating Garbage"? Durante il periodo di validità la generazione di possesso viene riempita e viene richiesto un GG completo, tuttavia richiede un po 'di tempo.

Inoltre, in questo caso particolare, non si raccoglie l'intera raccolta minore e, idealmente, nulla entra nella generazione di possesso? Tutti questi sono oggetti di breve durata.

risposta

2

Hai 1 istanza di String alive quando il GC è in corso (il riferimento forte all'interno del ciclo while) in modo che uno è quello che sopravvive da qui l'8k.

In questo caso, non chiamerei la raccolta dati di riferimento. Garbage floating è quando un oggetto non era pronto per essere sottoposto a GC quando il GC lo controllava, ma era pronto al termine del GC. Un esempio di ciò sarebbe.

Thread1: Person p = new Person("sammy") 

    Thread2: gc runs and sees that the Person instance is reachable through p. 

Thread1: p = null; // This Person instance is now unreachable. 

    Thread2: GC finishes. The person instance could have been collected but was reachable at the time the collector checked it. 
0

Non penso che la vostra misurazione sia accurata.

In primo luogo, quando si verifica un GC, l'Eden viene cancellato e gli oggetti sopravvissuti vanno nello spazio di Survivor. Quindi nel tuo caso, questo spiega perché YoungGen va da 16448K a 1616K: quei 1616K sono l'occupazione del sopravvissuto.

Nel frattempo, l'occupazione dell'heap totale dopo GC è 1624 K, il che significa che la vecchia generazione contiene in effetti 8 KB di dati.

Il termine "Garbage floating" si riferisce alle raccolte CMS, dove gli oggetti appena morti non vengono catturati dal raccoglitore. Non si applica a ParallelGC.

Per quanto riguarda il test case, gli oggetti String non andranno mai in Old Generation. Al massimo sopravviveranno a 1 ciclo di GC e andranno in uno spazio Survivor, e poi saranno recuperati

Speranza che aiuti!

+0

grazie. se gli oggetti stringa non entrano mai in Old Generation, perché l'heap (lentamente ma costantemente) si riempie dopo di che è richiesto un GC completo. Cosa pensi stia riempiendo di vecchio gen? –

+0

Ci sono almeno 20 altri thread in esecuzione nella JVM, non solo il thread "Main", quindi è abbastanza logico che alcuni oggetti vengano creati. Esempio: i thread del timer o i thread del GC stesso. La cosa importante è che dopo un GC completo, recuperi molta memoria. –

+0

@ N.M. Come un punto di vista, nota che Pierre ha detto che gli oggetti Stringhe nel tuo esempio non entreranno nel vecchio gen, non che gli oggetti stringa in generale non entrano mai in vecchio. – monkjack

Problemi correlati