Domanda

Cosa succede se si salva un riferimento all'oggetto corrente durante la chiamata di finalizzazione? Ad esempio:

class foo {
    ...
    public void finalize() {
        bar.REFERENCE = this;
    }
}

L'oggetto è stato garbage collection o no? Cosa succede quando si tenta di accedere a bar.REFERENCE in un secondo momento?

È stato utile?

Soluzione

L'oggetto non è garbage collection. Questo è noto come " Resurrection oggetto " ;.

Devi stare attento a questo, una volta chiamato finalizzatore il gc non lo chiamerà più, su alcuni ambienti come .NET puoi registrare nuovamente il finalizzatore ma non sono sicuro di java

Altri suggerimenti

Se devi assolutamente far risorgere oggetti, questo JavaWorld articolo suggerisce di creare una nuova istanza piuttosto che resuscitare l'istanza in fase di finalizzazione poiché se l'istanza in fase di finalizzazione diventa nuovamente idonea alla raccolta, verrà semplicemente raccolta (il finalizzatore non verrà eseguito nuovamente).

Questo genere di cose è il motivo per cui l'uso di finalize () è generalmente sconsigliato.

Poiché Java è un linguaggio e una piattaforma sicuri, la memoria non viene liberata. Anche i PhantomReference associati non saranno accodati sui loro ReferenceQueue . La VM chiamerà sempre finalize su un oggetto una sola volta. C'è un bel diagramma di stato nelle specifiche JVM.

In genere, se si utilizza un finalizzatore, è necessario lasciare la dichiarazione come @Override protetto void finalize () getta Throwable , in modo da non disturbare l'API. Ancora meglio usare un finalizzatore custodito, come in Effective Java 1st Ed.

Questo particolare trucco ha colpito i titoli (del San Jose Mercury, comunque) quando un gruppo di Princeton lo ha usato per costruire un ClassLoader personalizzato da codice non attendibile. Sebbene le specifiche siano state leggermente rafforzate (il costruttore Object deve terminare l'esecuzione normalmente prima di poter chiamare il finalizzatore - specificato in J2SE 5.0, implementato in Java SE 6), rimane ancora un'area problematica. Se stai progettando un'API, assicurati che le classi sensibili non possano essere sottoclassi e risparmierai molto dolore.

Il metodo finalize () può essere invocato esplicitamente nell'istanza foo oppure può essere richiamato dal garbage collector quando tenta di recuperare l'archiviazione occupata da tale oggetto.

Se bar è un'istanza valida, imposta il campo REFERENCE sull'istanza foo . Dal punto di vista del garbage collector, questo aumenta il conteggio dei riferimenti di foo .

Se viene generata un'eccezione all'interno del metodo finalize () (ad es. un NullPointerException a causa di bar essendo null ), quindi il processo di finalizzazione termina semplicemente.

NB. Come altri hanno sottolineato ... il tuo esempio è sicuramente qualcosa da evitare.

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