2011-11-19 21 views
10

Ho una classe java che utilizza campi statici complessi che necessitano di operazioni speciali come close() in modo che vengano puliti in modo sicuro da GC.Scarica campi statici

Per l'inizializzazione di campi statici utilizzo il blocco static. Ma ora non so come scaricare il campo statico in modo sicuro, in modo da poter chiamare il metodo close() prima che il campo venga ripulito da GC.

C'è un modo per scaricare un campo statico, simile al blocco di inizializzazione statico?

+1

Avete considerato l'uso di finalize()? –

+2

Ho. Ma da quello che so, finalizzo i lavori su oggetti di classe, non su campi statici di quella classe. Quindi, finalizzare non è un'opzione per me. –

+0

Forse usando un campo statico che contiene il numero di riferimenti attivi agli oggetti di quella classe (incrementato nel costruttore, decrementato in finalize()) E chiamando close() o qualsiasi altro metodo di pulizia che hai su quelle statiche "complesse" quando finalizzato () incontra un conteggio ref di 0 dopo il decremento farebbe - non ho provato questo, però. –

risposta

8

Non c'è un modo per fare ciò che si sta chiedendo perché il blocco statico viene inizializzato quando la classe è caricata e finalize() funziona solo sugli oggetti.

Considera di sostituire le variabili statiche e l'operazione complessa in esso con una classe Singleton e un'istanza di essa.

In questo modo, è possibile utilizzare un metodo finalize() per eseguire le azioni close().

-2

No.

classi statiche vengono caricati in fase di esecuzione prima volta che si utilizza, e scaricati solo quando si chiude il programma (AFAIK).

Quindi è possibile creare un metodo statico close nella classe stessa che pulisce i membri statici e chiamarlo quando si esce.

+1

E se si tratta di un'applicazione Web, come faccio a sapere quando esco? –

+0

no, le classi possono essere scaricate mentre un programma è ancora attivo. – jtahlborn

1

È possibile impostare un shutdown hook per eseguire questa operazione, ma potrebbe non essere possibile completare tutte le azioni. Potresti avere esaurito la memoria o il processo potrebbe essere stato eliminato senza che ciò desse la possibilità di eseguire la pulizia, ecc.

È meglio accertarsi che la consistenza dei dati non dipenda da questo codice e/o da spostare a codice che pulisce regolarmente durante la vita dell'applicazione.

+0

'ServletContextListener' è preferibile allo shutdown hook per le applicazioni Web. Vedi http://stackoverflow.com/questions/6950396/contextdestroyed-vs-addshutdownhook –

+0

@Kublai, nel contesto di un container servlet, sono d'accordo, l'OP non menziona comunque il contesto dell'app-web in nessuna parte della sua domanda. – rsp

+0

Lei lo menzionò nel suo commento alla risposta di Zom-B - d'accordo sul fatto che la domanda avrebbe dovuto dirlo. –

2

In un'app Web, si utilizzerà ServletContextListener.

+1

+1 Questa è la strada da percorrere, IMO. ['contextDestroyed()'] (http://download.oracle.com/javaee/6/api/javax/servlet/ServletContextListener.html#contextDestroyed (javax.servlet.ServletContextEvent)) viene chiamato esattamente una volta su undeploy. Se necessario, ['contextInitialized()'] (http://download.oracle.com/javaee/6/api/javax/servlet/ServletContextListener.html#contextInitialized (javax.servlet.ServletContextEvent)) può anche essere usato per inizializzare esplicitamente questi campi statici sulla distribuzione, piuttosto che attendere che la loro particolare classe venga caricata. –

3
private static Uninit cleanup = new Uninit(); 
.... 
private static class Uninit { 
    public Uninit() {} 

    public void finalize() { 

        //whatever you need done 

    } 
} 
+0

Questo sembra un trucco accurato se si vuole evitare di implementare un singleton. Potresti anche usare una classe anonima privata. Ci sono dei lati negativi su questo? – Griddo

+0

Funzionerà solo se i finalizzatori vengono effettivamente chiamati. –