Domanda

Quali sono le radici della garbage collection?

Ho letto la definizione di root come "qualsiasi riferimento a cui il programma può accedere" e la definizione di live è che un oggetto che viene utilizzato, che può essere una variabile locale e statica.

Sono poco confuso nel discriminare la differenza tra oggetti di radice e vivi.

Qual è il percorso verso la root? Come funzionano gli oggetti di root e vivi?

Qualcuno può elaborare?

È stato utile?

Soluzione

Se si pensi agli oggetti in memoria come un albero, le "radici" sarebbero i nodi radicali - ogni oggetto immediatamente accessibile dal tuo programma.

Person p = new Person();
p.car = new Car(RED);
p.car.engine = new Engine();
p.car.horn = new AnnoyingHorn();

Ci sono quattro oggetti; una persona, un'auto rossa, il suo motore e il corno. Disegna il grafico di riferimento:

     Person [p]
        |
     Car (red)
   /           \
Engine    AnnoyingHorn

E finirai con Person alla "radice" dell'albero. È live perché è citato da una variabile locale, p, che il programma potrebbe utilizzare in qualsiasi momento per fare riferimento a Person oggetto. Questo vale anche per gli altri oggetti, attraverso p.car, p.car.engine, eccetera.

Da Person E tutti gli altri oggetti in modo ricorsivo ad esso sono in diretta, ci sarebbero problemi se il GC li avesse raccolti.

Considera, tuttavia, se il seguente viene eseguito dopo un po ':

p.car = new Car(BLUE);

E ridisegnare il grafico:

     Person [p]
        |
     Car (blue)       Car (red)
                    /           \
                Engine    AnnoyingHorn

Ora il Person è accessibile attraverso p E l'auto blu attraverso p.car, ma non è possibile accedere di nuovo all'auto rossa o alle sue parti: non sono collegati a una radice dal vivo. Possono essere raccolti in modo sicuro.

Quindi si tratta davvero di prendere ogni punto di partenza (ogni variabile locale, globale, statica, tutto in altri thread e frame di stack) - ogni radice - e seguire ricorsivamente tutti i riferimenti per compensare un elenco di tutti gli oggetti "live": Oggetti che sono in uso e inadatti per la cancellazione. Tutto il resto è spazzatura, in attesa di essere raccolta.

Altri suggerimenti

Le radici GC (Garbage Collector) sono oggetti speciali per il collezionista di immondizia. Il Garbage Collector raccoglie quegli oggetti che non sono radici GC e non sono accessibili dai riferimenti dalle radici GC.

Esistono diversi tipi di radici GC. Un oggetto può appartenere a più di un tipo di radice. I tipi di radice sono:

  • Classe - Classe caricata dal caricatore di classe di sistema. Tali classi non possono mai essere scaricate. Possono contenere oggetti tramite campi statici. Si prega di notare che le classi caricate da caricatori di classe personalizzati non sono radici, a meno che le corrispondenti istanze di java.lang.class sono radici di altri tipi.
  • Discussione: thread dal vivo
  • IMPATTO LOCALE - Variabile locale o parametro del metodo Java
  • JNI Local - Variabile locale o parametro del metodo JNI
  • JNI Global - RIFERIMENTO JNI globale
  • Monitor utilizzato - Oggetti utilizzati come monitor per la sincronizzazione
  • Tenuto da JVM - Oggetti detenuti dalla Garbage Collection da JVM per i suoi scopi. In realtà l'elenco di tali oggetti dipende dall'implementazione di JVM. Possibili casi noti sono: il caricatore di classi di sistema, alcune importanti classi di eccezioni che conosce JVM, alcuni oggetti pre-allocati per la gestione delle eccezioni e caricanti di classe personalizzati quando sono in fase di caricamento delle classi. Sfortunatamente, JVM non fornisce assolutamente ulteriori dettagli per tali oggetti. Pertanto spetta all'analista decidere a quale caso appartiene una certa "detenuta da JVM".

(credito a Il sito web di Yourkit)

Non menzionato da yourkit è il fatto che gli oggetti in attesa di finalizzazione saranno mantenuti come radici fino a quando il GC esegue il finalize() metodo. Ciò può causare una ritenzione transitoria di grafici di grandi dimensioni in qualche modo inaspettatamente. La regola generale non è quella di utilizzare i finalizzatori (ma questa è una domanda diversa).

Roots o Garbage Collection Roots sono gli oggetti che sono sempre raggiungibile. Se un oggetto è sempre raggiungibile, non è idoneo per la raccolta dei rifiuti; Le radici sono quindi sempre non ammissibili per la raccolta. È determinato l'insieme iniziale di oggetti da cui vengono determinati la raggiungibilità di tutti gli altri oggetti sul heap.

Altri oggetti sul mucchio raggiungibili dalle radici della collezione di immondizia sono considerati come oggetti vivi, e non ammissibile per la raccolta; Gli oggetti irraggiungibili possono essere contrassegnati per la bonifica.

Conosco Java più della piattaforma .NET, quindi ne parlerò solo. Sulla piattaforma Java, le radici GC sono effettivamente dipendenti dall'implementazione. Nella maggior parte dei tempi di esecuzione, tuttavia, le radici GC tendono ad essere gli operandi sullo stack (poiché sono attualmente in uso per thread) e membri di classe (statici) delle classi. La raggiungibilità è calcolata da questi oggetti nella maggior parte dei JVM. Esistono altri casi in cui i parametri e gli operatori locali utilizzati dalle chiamate JNI saranno considerati parte del set di root e utilizzati anche per calcolare la raggiungibilità.

Spero che questo chiarisca qualsiasi dubbio persistente su ciò che è una root (set) e ciò che è un oggetto dal vivo.

Il Sito Web IBM Elenca quanto segue come radici GC.

Si noti che alcuni di questi sono costrutti artificiali realizzati da un analizzatore di memoria, ma comunque importanti di cui essere consapevoli se si guarda a un dump heap.

  • Classe di sistema

    Una classe che è stata caricata dal caricatore bootstrap o dal caricatore di classe di sistema. Ad esempio, questa categoria include tutte le classi nel file rt.jar (parte dell'ambiente di runtime Java), come quelle nel pacchetto Java.util.*.

  • Jni locale

    Una variabile locale nel codice nativo, ad esempio il codice JNI definito dall'utente o il codice interno JVM.

  • JNI Global

    Una variabile globale nel codice nativo, ad esempio il codice JNI definito dall'utente o il codice interno JVM.

  • Blocco filo

    Un oggetto a cui è stato fatto riferimento da un blocco thread attivo.

  • Filo

    Un thread in esecuzione.

  • Monitor occupato

    Tutto ciò che chiamava i metodi wait () o notify () o che è sincronizzato, ad esempio chiamando il metodo sincronizzato (oggetto) o inserendo un metodo sincronizzato. Se il metodo era statico, la radice è una classe, altrimenti è un oggetto.

  • Java locale

    Una variabile locale. Ad esempio, parametri di input o oggetti di metodi creati localmente che sono ancora nella pila di un thread. Stack nativo

    Parametri di input o output nel codice nativo, ad esempio il codice JNI definito dall'utente o il codice interno JVM. Molti metodi hanno parti native e gli oggetti che vengono gestiti come parametri del metodo diventano radici di raccolta della spazzatura. Ad esempio, i parametri utilizzati per file, rete, I/O o operazioni di riflessione.

  • Finalizzatore

    Un oggetto che si trova in coda, in attesa di funzionamento di un Finalizzatore.

  • UNINFINIZIONE

    Un oggetto che ha un metodo di finalizzazione, ma non è stato finalizzato e non è ancora nella coda del finalizzatore.

  • Irraggiungibile

    Un oggetto irraggiungibile da qualsiasi altro radice, ma è stato contrassegnato come analizzatore di memoria in modo che l'oggetto possa essere incluso in un'analisi.

    Gli oggetti irraggiungibili sono spesso il risultato di ottimizzazioni nell'algoritmo della raccolta dei rifiuti. Ad esempio, un oggetto potrebbe essere un candidato per la raccolta della spazzatura, ma sii così piccolo che il processo di raccolta dei rifiuti sarebbe troppo costoso. In questo caso, l'oggetto potrebbe non essere raccolto e potrebbe rimanere come un oggetto irraggiungibile.

    Per impostazione predefinita, gli oggetti irraggiungibili sono esclusi quando l'analizzatore di memoria analizza il dump heap. Questi oggetti non sono quindi mostrati nell'istogramma, nell'albero dei dominatori o nei risultati delle query. È possibile modificare questo comportamento facendo clic su File> Preferenze ...> Strumenti diagnostici IBM per Java - Analizzatore di memoria, quindi selezionando la casella di controllo Mantieni gli oggetti non raggiungibili.

  • Frame stack java

    Un frame stack Java, che contiene variabili locali. Questo tipo di radice di raccolta della spazzatura viene generato solo se si impostano le preferenze per trattare i frame dello stack Java come oggetti. Per ulteriori informazioni, consultare le basi di Java: thread e query di thread stack.

  • Sconosciuto

    Un oggetto di tipo radice sconosciuto. Alcuni dump, come i file di dump heap portatile IBM (.PHD), non hanno informazioni sul root. In questo caso, il parser analizzatore di memoria segna gli oggetti che non hanno riferimenti in entrata o sono irraggiungibili da qualsiasi altra radice, come sconosciuto. Questa azione garantisce che l'analizzatore di memoria mantenga tutti gli oggetti nel dump.

In Java direi che i thread sono gli oggetti di root. Ogni oggetto live può essere tornato a un thread dal vivo. Ad esempio, un oggetto statico è citato da una classe, a cui si fa riferimento da un caricatore di classe, a cui si fa riferimento da un'altra classe, a cui si fa riferimento da un'istanza di quella classe, ... a cui si fa riferimento da un Runnable, a cui si fa riferimento da un thread dal vivo. (Nota, le lezioni possono essere gc, non possono essere radici)

Possiamo anche considerare una radice "reale" per tutti i thread, tuttavia è fuori dal regno di Java standard. Non possiamo dire di cosa si tratta e come fa riferimento a tutti i thread.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top