2009-05-21 7 views

risposta

1

Invocando System.gc() il garbage collector è gestito, come dice il nome. A questo punto, quando gli oggetti vengono realmente rimossi, lo finalize() viene richiamato su questi oggetti prima che svaniscano.

L'ultima domanda non dovrebbe avere un "or" in esso. È la raccolta rifiuti n. e prestazioni ridotte.

Di solito non è necessario preoccuparsi gc a tutti perché è davvero un buon lavoro per voi. Esistono scenari di utilizzo in cui si desidera eliminare un sacco di oggetti in un determinato momento; Allora è fattibile.

+13

System.gc() non invoca necessariamente il GC. È solo un suggerimento alla JVM che è il momento giusto per eseguire il GC, ma la decisione finale di eseguirlo spetta alla JVM. – coobird

+0

Mi aspetto che i tempi in cui gc non viene eseguito se si chiama System.gc() piuttosto basso. D'altra parte gc viene eseguito completamente solo se vengono raggiunte le soglie. Invocando gc() di solito solo gc prima. –

+1

Con una singola CPU, se si usa System.gc() e si ha molto da pulire, si può vedere un vero picco di prestazioni fino al completamento della pulizia. Questo può essere davvero doloroso se ti avvicini al limite massimo di memoria della tua attività JVM e automaticamente esegue un GC serio su se stesso. Ma se hai più CPU, i problemi di prestazioni sono molto inferiori perché GC può accadere sull'altra CPU e il resto della tua JVM si muove allegramente lungo ... – jlarson

8

Esattamente ciò che accade quando si chiama System.gc() dipende da JVM. La JVM considera questa chiamata come un suggerimento che potrebbe essere un buon momento per eseguire il garbage collector, quindi non fare affidamento su di esso.

Il metodo finalize() di un oggetto viene eseguito su un oggetto dal garbage collector quando la JVM determina che non ci sono più riferimenti raggiungibili a tale oggetto. Non dovresti chiamarlo nel tuo codice. Ricordare che finalize() è non chiamato nel momento in cui il programma perde il riferimento finale, ma in un momento futuro in cui viene eseguito il garbage collector, quindi non dipendere dal fatto che si verifichi in un momento specifico nel tempo (o del tutto).

0

finalize() è un mezzo per eseguire bit finale di codice immediatamente prima che l'oggetto è pronto per la raccolta dei rifiuti (quando l'oggetto non ha forte riferimento ad esso).

Quindi quando dovrebbe essere utilizzato? Solo nelle presenti due casi:

  1. Come sicurezza per assicurarsi che un certo servizio viene chiusa o qualche cambiamento finale desiderato è fatto. Ad esempio, la classe InputStream lo utilizza per chiudere il flusso di i/o. Ad esempio, hai creato un'istanza di BufferedInputStream. Manualmente dopo averlo usato uno è supponiamo di chiuderlo(). Ma perché si può dimenticare di farlo, finalize() atto è come una rete di sicurezza per chiudere() il flusso.
  2. Mentre utilizzando Native's. Poiché Garbage Collector non ha alcun controllo sugli oggetti nativi , finalize() può essere utilizzato come mezzo per riprenderlo.

Oltre ai due casi precedenti, non utilizzarlo mai. Per capire perché? abbiamo bisogno di capire il funzionamento e il ciclo di vita di un oggetto.

Introduzione: esiste un thread daemon separato chiamato thread di finalizzazione responsabile della chiamata al metodo finalize(). La coda di finalizzazione è il punto in cui sono collocati gli oggetti che sono pronti per essere chiamati metodo finalize().

  1. Quando viene creato un oggetto, JVM controlla se l'oggetto ha un metodo finalize(). Se ha allora nota internamente che questo particolare oggetto ha il metodo finalize().

Quando un oggetto è pronto per la raccolta dei rifiuti, poi i garbage collector filo controlla se questo particolare oggetto contiene finalizzare() dalla tabella di cui (1).

  • 2a) Se non allora è inviato per la raccolta dei rifiuti.

    2b) È ha, quindi viene aggiunto alla coda di finalizzazione. E rimuove la voce dell'oggetto dalla tabella (1).

Il thread del finalizzatore continua a interrogare la coda. Per ogni oggetto in coda, viene chiamato il metodo finalize(). Dopo aver chiamato il ciclo finalize() da (2) viene nuovamente ripetuto. Se questo oggetto non ha ancora un riferimento forte, quindi inviato per GC. Se ha poi SEMPRE (2a) è chiamato perché la voce è stata eliminata in (2b)

Basically finalize() method is only called once. 

Allora qual è il problema con il ciclo di cui sopra?

Da (1). È necessario più tempo per la creazione di oggetti. L'allocazione della memoria in Java è 5x a 10 volte più veloce di malloc/calloc ecc. Tutto il tempo guadagnato viene perso nella procedura di annotazione dell'oggetto nella tabella, ecc. Una volta l'ho provato. Crea 100000 oggetti in un ciclo e misura il tempo impiegato dal programma per terminare in 2 casi: uno senza finalize(), il secondo con finalize(). Trovato per essere il 20% più veloce.

Da (2b): perdita di memoria e carenza di cibo. Se l'oggetto nella coda ha riferimenti a molte risorse di memoria, allora tutti questi oggetti non verranno liberati a meno che questo oggetto non sia pronto per GC. Se tutti gli oggetti sono oggetti pesanti, allora ci può essere una carenza.

Da (2b): Perché finalize() viene chiamato una sola volta, cosa succede se in te finalize() hai un forte riferimento a "questo" oggetto. La prossima volta che finalie dell'oggetto() non viene mai chiamato, quindi può lasciare l'oggetto in uno stato incoerente.

Se all'interno finalize() viene generata un'eccezione, viene ignorata.

Non si sa quando finalize() viene chiamato poiché non si ha controllo su quando viene chiamato GC. A volte può capitare che stiate stampando il valore in finalize() ma l'output non viene mai mostrato, perché il vostro programma potrebbe essere terminato prima che venga chiamato finalize().

Quindi evitare di utilizzarlo. Piuttosto, crea un metodo dire dispose() che chiuderà le risorse necessarie o per il registro finale, ecc. the complete post on it. Spero che questo chiarisca.

+0

Stack Overflow preferisce fornire contenuti nella risposta, non solo un collegamento. Se il link interrompe la risposta non avrà alcun valore. –

+1

Fatto !! Grazie per il suggerimento – Jatin

0

System.gc() ripulisce la memoria e utilizza finalize() per sbarazzarsi dei singoli oggetti.

0

Sì System.gc(); attiverà il metodo finalize() se necessario. class TestGarbageCollection pubblico {

public static void main(String[] args) { 
    while (true) { 
     TestClass s = new TestClass(); 
     s.display(); 
     System.gc(); 
    } 
} 

}

pubblico class TestClass {

public TestClass() { 
    System.out.println("constructor"); 
} 

public void display() { 
    System.out.println("display"); 
} 
@Override 
public void finalize() { 
    System.out.println("destructor"); 
} 

}

Questo attiverà metodo Finalize(). se si esegue l'override del metodo finalize o non finalize della classe locale, verrà chiamato il finalize dell'oggetto.

+0

Non è vero !! È su JVM se il metodo finalize debba essere chiamato durante la garbage collection o meno. E anche come per Java-doc, chiamare 'System.gc' non garantisce che invochi immediatamente Garbage Collector per la liberazione della memoria. È solo il suggerimento !!! –

+0

@Arun Kumar: Sebbene l'Oracle System.gc() JavaDocs dica: "La chiamata di questo metodo suggerisce che Java Virtual Machine impieghi sforzi per eseguire i metodi finalizzati di oggetti che sono stati trovati scartati ma i cui metodi di finalizzazione non sono stati ancora run. ** Quando il controllo ritorna dalla chiamata al metodo, la Java Virtual Machine ha fatto il massimo sforzo per completare tutte le finalizzazioni in sospeso. ** "La frase finale è molto chiara. E la frase subito prima confonde l'acqua. Vorrei che aggiustassero quei documenti già, perché ora non so cosa pensare. –

Problemi correlati