2012-01-20 10 views
10

Sto combattendo per problemi di memoria con la mia applicazione e sto cercando di capire come funziona la garbage collection. Se ho il seguente codice:A che punto è esattamente un oggetto disponibile per la garbage collection?

public void someMethod() { 
    MyObject myObject = new MyObject(); 
    myObject.doSomething(); //last use of myObject in this scope 
    doAnotherThing(); 
    andEvenMoreThings(); 
} 

Quindi la mia domanda è, sarà myObject disponibile per la raccolta dei rifiuti dopo myObject.doSomething() che è l'ultimo uso di questo oggetto, o dopo il completamento di someMethod() dove viene fuori del campo di applicazione? Cioè la garbage collection è abbastanza intelligente da vedere che sebbene una variabile locale sia ancora in ambito, non verrà utilizzata dal resto del codice?

+1

Penso che stai usando "dereferenziato" nel contesto sbagliato. – isah

+1

Solo perché il garbage collector vede che non è usato non man che sceglierà di liberarlo subito - non dovresti scrivere codice che dipende dal comportamento di un evento imprevedibile;) SE hai problemi di memoria probabilmente stai mantenendo i riferimenti a qualcosa per errore :( – deanWombourne

+0

Hmm, grazie isah, penso che tu abbia ragione, aggiornerò il titolo alla domanda: –

risposta

4

"Dove viene fuori del campo di applicazione"

public void someMethod() { 
    MyObject myObject = new MyObject(); 
    myObject.doSomething(); //last use of myObject in this scope 
    myObject = null; //Now available for gc 
    doAnotherThing(); 
    andEvenMoreThings(); 
} 
+0

si verificherà alla riga 4 perché è stato esplicitamente dereferenziato myObject = null; // ora disponibile per gc –

+0

Sì corretto. – Farmor

+1

nella domanda anche se terminerà dopo il riccio corri perché non c'è il dereferenziamento. –

2

Dopo ambito locale è fuori. come oggetto può essere riutilizzato e può vivere nell'ambito locale. vale a dire. è contrassegnato per gc. ma non in realtà gc'ed.

2

Ottimizzazione del codice sarà probabilmente notato in cui l'ultimo utilizzo di myObject è e renderlo disponibile per la garbage collection lì, comunque tecnicamente sarà fino a quando la variabile non si riferisce più ad essa (per essere assegnato ad altro) o va fuori dal campo di applicazione.

+0

Non penso che sia effettivamente consentito dal JLS - o almeno l'hotspot non lo fa. NET DOES consente effettivamente esattamente ciò che significa che abbiamo [GC.KeepAlive] (http://msdn.microsoft.com/en-us/library/system.gc.keepalive.aspx) per evitare di raccogliere oggetti (ad esempio timer) con effetti collaterali prima di quanto vorremmo. Almeno in Java non mi sono mai imbattuto in alcuna menzione di ciò che mi avrebbe sorpreso. – Voo

+0

Interessante. Per ottimizzazione del codice, intendi l'esecuzione JVM, l'esecuzione GC o la compilazione del codice? –

4

La cosa migliore che puoi fare è prendere il tuo codice mettendolo in loop con un ritardo e collegando un profiler ad esso.

Se si utilizza una versione successiva di Java, JVisualVm viene fornito come standard.

Se siete su Windows e impostare JAVA_HOME

% JAVA_HOME%/bin/jvisualvm

Questo lancerà un profiler e si può vedere quali oggetti vengono raccolti e ciò che non lo sono . Secondo me questa è una parte essenziale dell'essere un programmatore ed è divertente trovare le perdite di memoria.

Spero che questo aiuti

+0

+1 per il consiglio del profiler – helios

4

Btw in seguito Java 6, v'è il tipo di escape analysis dove JVM può scoprire che l'istanza di MyObject non lascia il metodo, in modo che anche possibile inserirlo interamente su stack e si non avrà bisogno di alcun GC per questo.

3

Quindi la mia domanda è, sarà MyObject disponibile per la raccolta dei rifiuti dopo myObject.doSomething(), che è l'ultimo uso di questo oggetto, o dopo il completamento di someMethod() dove viene fuori del campo di applicazione?

Il primo.

I.e. la garbage collection è abbastanza intelligente da vedere che sebbene una variabile locale sia ancora in ambito, non verrà utilizzata dal resto del codice?

L'ambito non è visibile al GC che vede solo registri, stack, variabili globali e riferimenti da blocchi heap ad altri blocchi heap. Quindi la portata è irrilevante.