2012-10-30 9 views
10

Nel codice seguente, dato che è stato chiamato amethod. A che punto/linea è l'oggetto originariamente referenziato da myObject, idoneo per Garbage Collection?Quando l'oggetto è idoneo per la raccolta dati inutili?

class Test { 
    private Object classObject; 

    public void amethod() { 
    Object myObject = new Object(); 
    classObject = myObject; 
    myObject = null; 
    } 
} 

E se classObject o amethod avevano un modificatore di accesso del pubblico, protetto, di default o statico, sarebbe influenzare ciò che punto l'oggetto è ammissibile per Garbage Collection? Se sì, come ne risentirebbe?

  • Il mio primo pensiero è che l'oggetto sia idoneo per Garbage Collection quando l'oggetto Test è idoneo per Garbage Collection.
  • Ma poi di nuovo. L'ottimizzatore potrebbe sapere che il classObject non viene mai letto dal caso in cui classObject = myObject; verrà ottimizzato e myObject = null; è il punto idoneo per Garbage Collection.
+0

Quando si dice "l'oggetto", si fa riferimento all'istanza della classe 'Test',' Object classObject' o 'Object myObject'? –

+0

@LuiggiMendoza "l'oggetto" fa sempre riferimento all'oggetto originariamente indicato da myObject. – Dorothy

risposta

15

L'oggetto non può diventare un candidato per la garbage collection fino al tutti i riferimenti vengono scartati. Gli oggetti Java sono assegnati per riferimento, quindi quando si aveva

classObject = myObject; 

È stato assegnato un altro riferimento allo stesso oggetto sull'heap. Così questa linea

myObject = null; 

solo si libera di un riferimento. Per rendere myObject un candidato per la raccolta dei rifiuti, è necessario disporre di

classObject = null; 
+0

I compilatori non consentono di ottimizzare l'assegnazione di ivar come descritto nella domanda? –

+0

Sulla base di una varietà di fattori incluso il tipo di riferimento (debole vs soft), non è semplice (o sicuro) dipendere da questa ottimizzazione in ogni caso @KartickVaddadi – kolossus

+0

@VaddadiKartick: la specifica dichiara * esattamente * che questo tipo di ottimizzazione non è consentito per una variabile heap. Vedi [questa risposta] (https://stackoverflow.com/a/47311943/2711488) ... – Holger

0

Nessun oggetto è per la garbage collection qui perché si sta creando due di riferimento per lo stesso oggetto e si stanno dando nulla per un solo riferimento, ma altri di riferimento è ancora puntando l'oggetto

0

Dal momento che si sta svolgendo myObject a classObject (viene mantenuta riferimento), esso (oggetto in riferimento alla memoria attraverso classObject) non sarà disponibile per la garbage collection fino istanza di Test è liberato/scarico.

+0

dopo aver eseguito il metodo 'amethod',' myObject' diventerà disponibile per GC ma 'classObject' no. –

2

La tua idea che l'oggetto privato possa essere GC subito perché nessun altro codice è in grado di accedervi ha una certa trazione, ma questo potrebbe compromettere la semantica generale della gestione della memoria Java. Ad esempio, se l'oggetto implementato è finalize e la semantica di Java indica chiaramente quando un oggetto è idoneo per la garbage collection, il metodo di finalizzazione deve essere chiamato contro la specifica.

Si noti inoltre che l'oggetto a sua volta può fare riferimento ad altri oggetti, con risultati ancora più complicati possibili. Per non parlare del fatto che l'oggetto è raggiungibile in qualunque momento da Reflection e non avrebbe senso che il campo da osservare cambi improvvisamente in null anche se nessun codice avrebbe potuto eseguire quell'assegnazione.

Per concludere, ci sono molte ragioni per cui la tua idea di ottimizzazione non funzionerebbe nel quadro più ampio.

+0

Il motivo più forte è che [è stato escluso esplicitamente dalla specifica] (https://stackoverflow.com/a/47311943/2711488) ... – Holger

1

Nel seguente codice, dato che è stato chiamato amethod. A che punto/linea è l'oggetto originariamente referenziato da myObject, idoneo per Garbage Collection?

La tua domanda è priva di senso, perché c'è uno scollamento tra il codice sorgente di alto livello e la rappresentazione di basso livello (radici globali nei registri, nello stack e le variabili globali) che il garbage collector vede.

La frase "eleggibile per garbage collection" indica presumibilmente a che punto un blocco di memoria allocata nell'heap diventa irraggiungibile. Quindi la tua domanda può essere risolta solo formulando un sacco di (discutibili) ipotesi su quale allocazione dell'heap e per quanto tempo il codice generato manterrà i riferimenti.

1

Da Prenota OCA Java SE 7

Un oggetto è contrassegnato come ammissibili essere garbage collection quando non può più essere raggiunto, che può accadere quando l'oggetto esce di scopo. Può anche accadere quando la variabile di riferimento di un oggetto è assegnata a un valore nullo esplicito o viene reinizializzata.

1

Questo è effettivamente indirizzata proprio dal linguaggio Java Specification, §12.6.1, Implementing Finalization:

Ottimizzazione trasformazioni di un programma possono essere progettati che riducono il numero di oggetti che sono raggiungibili a essere inferiori a quelle che avrebbe ingenuamente essere considerato raggiungibile. Ad esempio, un compilatore o un generatore di codice Java può scegliere di impostare una variabile o un parametro che non sarà più utilizzato per null affinché l'archiviazione per tale oggetto sia potenzialmente recuperabile prima.

Un altro esempio di ciò si verifica se i valori nei campi di un oggetto sono memorizzati nei registri. Il programma può quindi accedere ai registri anziché all'oggetto e non accedere più all'oggetto. Ciò implicherebbe che l'oggetto è spazzatura. ...

Ma

... Si noti che questo tipo di ottimizzazione è consentito solo se i riferimenti sono in pila, non memorizzata nel mucchio.

Ad esempio, si consideri il modello di Finalizer Guardian:

class Foo { 
     private final Object finalizerGuardian = new Object() { 
      protected void finalize() throws Throwable { 
       /* finalize outer Foo object */ 
      } 
     } 
    } 

il finalizzatore forze guardiano super.finalize di essere chiamato se una sottoclasse sovrascrive finalize e non richiama esplicitamente super.finalize.

Se queste ottimizzazioni sono consentite per i riferimenti archiviati nell'heap, un compilatore Java può rilevare che il campo finalizerGuardian non viene mai letto, annullato, raccolto immediatamente l'oggetto e chiama il finalizzatore in anticipo. Ciò va contro l'intento: il programmatore probabilmente voleva chiamare il finalizzatore Foo quando l'istanza Foo non era raggiungibile. Questo tipo di trasformazione non è quindi legale: l'oggetto della classe interna dovrebbe essere raggiungibile fintanto che l'oggetto della classe esterna è raggiungibile.

Questo esempio può essere applicato 1: 1 per il tuo esempio, fino a quando l'oggetto viene riferimento il campo di istanza classObject, non può ottenere garbage collection prima di quanto l'istanza Test contenente il riferimento.

Si noti, tuttavia, che le ottimizzazioni aggressive menzionate nelle specifiche sono ancora consentite, quando vengono applicate al codice utilizzando l'istanza Test. È possibile che si verifichi la raccolta precedente alle aspettative, purché sia, sia l'istanza Test e l'oggetto di riferimento vengano raccolti insieme. In questo caso, si applica il seguente aspetto specificato in §12.6:

Il linguaggio di programmazione Java non impone alcun ordine sulle chiamate di metodo finalizzate. I finalizzatori possono essere chiamati in qualsiasi ordine, o anche contemporaneamente.

Quindi è perfettamente possibile che l'istanza Test viene raccolto prima di quanto l'oggetto a cui fa riferimento, mentre classObject finalizzatore di un oggetto “interiore” viene richiamato in precedenza. L'unica cosa che è garantita è che, quando viene eseguito il finalizzatore dell'oggetto interno, l'oggetto esterno non è raggiungibile (o ha una finalizzazione in sospeso o simultanea). Dal momento che nel tuo esempio, nessuno dei due ha un finalizzatore non banale, non importa comunque ...

Problemi correlati