2011-11-11 1 views
5

Ho monitorato la mia applicazione java con profiler per conoscere la perdita di memoria. E ho avuto classe che prendendo quasi l'80% della memoria che èCome aumentare la priorità di FinalizerThread per raccogliere oggetti in GC

java.lang.ref.Finalizer 

Poi ho google per la classe di cui sopra e ho trovato grande articolo http://www.fasterj.com/articles/finalizer1.shtml

Ora uno può suggerire come faccio ad aumentare la priorità di FinalizerThread a raccogliere tali oggetti in GC.

Una cosa che sto affrontando questo tema su Linux con la versione del kernel di Linux 2.6.9-5.ELsmp (i386) e Linux 2.6.18-194.17.4.el5 (i386) ma sta lavorando bene (senza errore OOM) su Linux 2.6.18-128.el5PAE (i386).

Questo problema è dovuto a Kernel Linux? C'è qualche variabile JVM per migliorare la priorità di FinalizerThread?

Grazie in anticipo.

+1

Buona domanda, penso che in generale sia necessario ridurre al minimo l'uso di Finalizzatori. –

+0

Forse in modalità PAE hai semplicemente più memoria disponibile (non PAE è limitato a 4 GB) - seleziona 'free'. Non penso che la versione del kernel sia in gioco qui. –

+0

Grazie Dan, come suggerisce Peter di seguito, ora sto verificando con il file system. – user1041580

risposta

2

Per rispondere alla domanda alla lettera puoi farlo. Tuttavia, come indicato di seguito, è probabile che sia inutile, specialmente perché il Thread ha già una priorità elevata.

for(Thread t: Thread.getAllStackTraces().keySet()) 
    if (t.getName().equals("Finalizer")) { 
     System.out.println(t); 
     t.setPriority(Thread.MAX_PRIORITY); 
     System.out.println(t); 
    } 

stampe

Thread[Finalizer,8,system] 
Thread[Finalizer,10,system] 

A meno che non si sta utilizzando il 100% di tutti i nuclei, o vicino ad esso, la priorità non importa, perché nemmeno la priorità più bassa sarà ottenere il più CPU come vuole

Nota: su Linux, ignorerà le priorità sollevate a meno che non si sia root.

Invece si dovrebbe ridurre il lavoro che sta facendo il finalizzatore. Idealmente non dovrebbe avere nulla da fare. Una causa di carico elevato nel finalizzatore è la creazione di risorse che dovrebbero essere chiuse ma vengono eliminate. (lasciando invece il finalizzatore per chiudere la risorsa)

In breve, dovresti provare e determinare quali risorse sono state finalizzate e assicurarti che non debbano fare nulla quando finalize() viene chiamato, idealmente non usare questo metodo a tutti.

È possibile che le risorse impieghino meno tempo per chiudersi sulla versione precedente del kernel Linux. Verificerei che l'hardware è identico in quanto ciò potrebbe significare che ci vuole più tempo per ripulire le risorse. (Ma la vera soluzione è assicurarsi che non sia necessario)

+0

java può fare la differenza. Perché i primi due Linux (dove sorge il problema di OOM), sto usando java a 64 bit e uno in cui funziona bene, sto usando 32 bit? – user1041580

+0

La versione Java, sia che si utilizzi 64 bit o 32 bit, quale hardware si utilizza CPU, memoria, disco, larghezza di banda della rete, il carico di lavoro, ad es. sta facendo un lavoro diverso, quanto sono impegnate le risorse da chiudere ad es. se si collegano a un database o un servizio fanno tutti la differenza in questo caso. La versione del kernel potrebbe fare la differenza, ma vorrei prima controllare il primo elenco. –

+0

Se si dispone di una versione precedente di Java, la versione a 64 bit può utilizzare più memoria rispetto alla versione a 32 bit. Se hai l'ultima versione la differenza è molto più piccola (dato che usa '-XX: + UseCompressedOops') La vera soluzione è quella di correggere il codice, non di armeggiare con la JVM. –

2

Il thread di finalizzazione dovrebbe raramente svolgere molto lavoro. Le risorse dovrebbero essere già state rilasciate. Assicurati che il tuo codice gestisca le risorse nel modo standard.

Java SE 7:

try (final Resource resource = acquire()) { 
    use(resource); 
} 

pre-Java SE 7:

final Resource resource = acquire(); 
try { 
    use(resource); 
} finally { 
    resource.release(); 
} 
0

Come Tom Hawtin fa notare, è possibile entrare in possesso del FinalizerThread creando un metodo finalize() che chiama Thread.currentThread() e poi lo nasconde in una statica. Probabilmente puoi anche cambiare la sua priorità.

Ma ci sono buone probabilità che non serva a niente. È probabile che ci sia solo un thread di finalizzazione. E il problema è probabile che sia uno che:

  • il filo non può tenere il passo perché c'è semplicemente troppo lavoro da fare, o
  • il thread è stato bloccato da qualcosa che si sta facendo nel finalizzatore metodi.

(E, mi aspetto il filo finalizzatore per già essere contrassegnato come priorità alta.)

Ma in entrambi i casi, penso che una soluzione migliore è quella di sbarazzarsi dei finalize() metodi. Scommetto che stanno facendo qualcosa che è o non necessario ... o dubbia. In particolare, l'utilizzo di finalizzatori per recuperare risorse da oggetti rilasciati è un modo scadente per risolvere quel particolare problema. (Vedi la risposta di Tom Hawtin.)

+0

Ottenere l'oggetto thread finalizzatore? Facile. Crea un oggetto con un finalizzatore che ha nascosto 'Thread.currentThread()' in una statica. –