2013-03-26 14 views
10

La mia applicazione ha molte iterazioni. Fino ad ora non ho affrontato alcun problema di memoria. Ma dal livello di codice posso sospettare che ci siano pochi posti, che causano perdite di memoria e problemi di memoria. Sto pensando di chiamare manualmente il garbage collector. È buona pratica chiamare Garbage Collector manualmente?Possiamo chiamare esplicitamente il Garbage Collector?

+0

Mi sembra che questa domanda fosse già trattata: http://stackoverflow.com/questions/2414105/why-is-it-a-bad-practice-to-call-system-gc –

risposta

26

È possibile chiamare collettore di immondizia con:

System.gc(); 

Ma questo non significa che sarà eseguito immediatamente. La JVM decide quando eseguirla. In generale, se la JVM sta per lanciare un OutOfMemoryError, chiamare System.gc() non lo impedirà. È meglio indagare sul motivo per cui si perde così tanta memoria e si pulisce lungo la strada.

JavaDoc:

chiamata al metodo GC suggerisce che la Java Virtual Machine spendere sforzo verso il riciclaggio oggetti inutilizzati al fine di rendere la memoria che attualmente occupano disponibili per il riutilizzo rapido. Quando il controllo torna dalla chiamata di metodo, la Java Virtual Machine ha fatto uno sforzo migliore per recuperare spazio da tutti gli oggetti di scarto

+9

+1 I ' d anche aggiungere che la chiamata System.gc può effettivamente degradare le prestazioni dell'applicazione – MadProgrammer

+3

Suppongo che sarebbe bello avere un elenco di casi in cui chiamare 'System.gc()' * è * utile. Un caso è un tentativo di stimare l'utilizzo della memoria, durante il debug/lo sviluppo (non la produzione). Un altro caso è un tentativo inaffidabile di chiamare i finalizzatori, per analizzare le perdite di memoria, ancora durante lo sviluppo. –

+1

@Thomas, finalizzatori/spazzatura di classe sono i motivi principali, i finalizzatori per le risorse di sistema come DirectBuffers/I descrittori di file sono importanti. L'opzione Morealso jmap w/live chiama la garbage collection. Ci sono diverse opzioni -XX per influenzare ciò che accade durante una chiamata esplicita (incluso totalmente nulla). Ci sono alcuni altri casi che possono avere un effetto positivo di avere un mucchio di risorse compatte (se la compattazione e il possesso sono in realtà un'opzione con il raccoglitore scelto) – bestsss

8

È una buona pratica di chiamare Garbage Collector manualmente?

No, non è sicuramente una buona pratica.

È possibile utilizzare System.gc(). Si noti che questo non è garantito per chiamare il garbage collector - dà solo un suggerimento al sistema che potrebbe essere una buona idea fare garbage collection.

Il garbage collector in JVM di Oracle contiene un sacco di logica sofisticata per determinare quando e cosa pulire. L'ottimizzazione richiede conoscenze sui dettagli su come funziona. Il solo inserimento di un numero System.gc() da qualche parte nel tuo programma non è di grande aiuto e, anzi, può addirittura peggiorarlo.

Vedi Java SE 6 HotSpot Virtual Machine Garbage Collection Tuning per i dettagli su come ottimizzare la raccolta dei rifiuti con Java SE 6.

+3

* No, non è sicuramente una buona pratica. * Non sarei d'accordo, se sai perché lo chiami, è un affare ok. Ciò sarebbe applicabile ad alcuni codici di monitoraggio, però. Darò un esempio chiamando MappedByteBuffer.map, è necessario ottenerlo finalizzato e l'unica opzione non-hack coinvolge il GC. – bestsss

+0

@bestsss - Ho interpretato "buona pratica" come "qualcosa che è comunemente una buona cosa da fare", e chiamare manualmente il GC in modo definitivo non è qualcosa che dovresti normalmente fare - fallo solo se sai davvero cosa stai facendo quando puoi provare a te stesso che è benefico. – Jesper

+0

Ovviamente chiamare senza motivo, è una cattiva idea. btw, un refuso nel commento precedente: MappedByteBuffer. * * Unmap – bestsss

3

Indipendentemente dal fatto che si può o non può attivare manualmente il garbage collector (e diversi livelli di raccolta), e quale impatto che questo ha sulla prestazioni (che in effetti è a topic worth discussion), non impedirà OutOfMemoryErrors, perché quando la JVM sta per esaurire la memoria, fa comunque la raccolta più completa possibile. Solo se dopo quella raccolta non è disponibile memoria sufficiente, si verificherà un errore. Anche se fai scattare la raccolta prima tu stesso, il risultato (la quantità di memoria recuperata) è la stessa.

Le perdite di memoria non possono essere risolte eseguendo la raccolta dati obsoleti più spesso.

Devono essere corretti nel programma (interrompere il riferimento a cose che non sono più necessarie in precedenza) o (nel peggiore dei casi, se si tratta di una perdita "reale" nella JVM o nella stessa libreria di runtime (ma vera memoria i bug di gestione non dovrebbero più esistere dopo tanti anni di servizio).

6

È possibile chiamare in modo esplicito Garbage Collector, ma JVM decide se elaborare la chiamata o meno. Idealmente, non si dovrebbe mai scrivere codice dipendente dalla chiamata al garbage collector.

JVM utilizza internamente un algoritmo per decidere quando effettuare questa chiamata. Quando si effettua una chiamata utilizzando System.gc(), è solo una richiesta a JVM e JVM può in qualsiasi momento decidere di ignorarlo.

5

Sì, è possibile chiamare esplicitamente garbage collector utilizzando

System.gc(); 

Ma quello che succede è che non si può ordinare JVM fare garbage collection immediatamente. JVM decide da solo quando effettuare il garbage collision. Quindi non è una buona idea chiamarlo manualmente.

Inoltre per quanto riguarda OutOfMemoryException fare garbage collection manuale non aiuterà a prevenire l'eccezione, poiché JVM lancia questa eccezione dopo aver recuperato tutta la memoria che può. Ha alcuni algoritmi molto sofisticati per determinare quando e come eseguire la garbage collection. Quindi quello che suggerisco è che se si ottiene OutOfMemoryException quindi ricontrollare il programma renderlo più efficiente o aumentare lo spazio heap.