2010-09-09 14 views
9

Probabilmente chiederai, perché dovrei farlo - è perché sto usando una classe (da una libreria esterna) che fa cose nel suo inizializzatore statico e ho bisogno di sapere se è stato fatto o meno.Come verificare se una classe è stata inizializzata?

Ho guardato a ClassLoader, ma non ho trovato nulla che sembrasse utile. Qualche idea?

+1

significa "se una classe è inizializzata". c'è un'enorme differenza. – irreputable

+0

Grazie per averlo indicato. Ho cambiato il titolo. – mik01aj

+1

Quale libreria? Forse c'è un effetto collaterale che è possibile verificare (ad esempio, i driver JDBC si registrano nel DriverManager). –

risposta

13

È possibile utilizzare il metodo ClassLoader.findLoadedClass(). Se restituisce null, la classe non viene caricata. In questo modo non carichi la classe se non è già stata caricata.


ATTENZIONE: Questo codice non funziona davvero qui, nel sistema di ClassLoader, findLoadedClass() è protetto, è necessario sostituire con il proprio ClassLoader.

Verificare sul link qui sotto Sullo stesso argomento per verificare se una classe viene caricato con il sistema di ClassLoader

if(ClassLoader.getSystemClassLoader().findLoadedClass("java.lang.String") != null){ 
    System.out.println("Yepee, String is loaded !"); 
} 

Molto buon punto da @irreputable:

"caricato" non significa "inizializzato". inizializzazione avviene solo in momenti precisi definiti da JLS3 $ 12.4.1

cito:

Una classe o interfaccia tipo T verrà inizializzato immediatamente prima del primo verificarsi di uno qualsiasi dei seguenti :

  • T è una classe e un'istanza di è creato T.
  • T è una classe e un metodo statico dichiarato dal T viene richiamato.
  • Viene assegnato un campo statico dichiarato da T.
  • Viene utilizzato un campo statico dichiarato da T e il campo non è una variabile costante (§4.12.4).
  • T è una classe di livello superiore, ed una dichiarazione assert(§14.10) lessicalmente nidificato all'interno T viene eseguito.

invocazione di taluni metodi riflettenti in classe Class e in pacchetto java.lang.reflect provoca anche classe o interfaccia inizializzazione. Una classe o un'interfaccia non verranno inizializzate in nessun'altra circostanza.


Risorse:

Sulla sa Mi argomento:

+0

Questo non comporterà il caricamento di 'String' quando si effettua la chiamata al metodo, in quanto deve valutare il valore letterale' String' '" java.lang.String "'? –

+0

Bene, il codice non funziona affatto, non possiamo chiamare findLoadedClass() sul programma di caricamento classi predefinito. Quindi considera questo come un semplice esempio. –

+0

Certo, un semplice esempio forzato, ma nondimeno, la tua istruzione 'if' non valuterà sempre a' true'? –

4

Perché non si fa semplicemente riferimento alla classe (creando un riferimento, creando un'istanza o accedendo a un membro statico)? In tal modo si avvierà l'inizializzatore del tipo se non è già stato attivato e se lo è, si è ancora pronti.

+0

Poiché questa libreria legge i parametri con 'System.getProperty' e ho bisogno di sapere se posso ancora cambiarli o meno. – mik01aj

2

È possibile ottenere la JVM di stampare le classi in quanto li carica, utilizzando il flag -verbose. Questo potrebbe esserti d'aiuto.

java -verbose Dummy|head 
[Opened C:\Program Files\Java\jre6\lib\rt.jar] 
[Loaded java.lang.Object from C:\Program Files\Java\jre6\lib\rt.jar] 
[Loaded java.io.Serializable from C:\Program Files\Java\jre6\lib\rt.jar] 
[Loaded java.lang.Comparable from C:\Program Files\Java\jre6\lib\rt.jar] 
[Loaded java.lang.CharSequence from C:\Program Files\Java\jre6\lib\rt.jar] 
[Loaded java.lang.String from C:\Program Files\Java\jre6\lib\rt.jar] 

(btw, appena provato questo su un programma Ciao Mondo ed è caricato su 309 classi wow!)

1

si può provare qualcosa di simile:

Class c = new ClassLoader() { Classe c = findLoadedClass (className); } .c;

+0

non funziona, restituirà sicuramente null. – irreputable

0
Class.forName("com.abc.Xyz", true, this.getClass().getClassLoader()) 

Si bloccherà fino a quando la classe è stata inizializzata (da sola o qualche altro thread)

0

Se non è troppo tardi .. Questo dovrebbe funzionare bene così

Class.forName().newInstance(); 

il newInstance() crea una nuova istanza della classe rappresentata da questo oggetto Class. La classe viene istanziata come da una nuova espressione con una lista di argomenti vuota. La classe viene inizializzata se non è già stata inizializzata.

1

So che è molto tardi, ma penso che questa risposta potrebbe essere utile. Se non siete troppo spaventati (e v'è permesso) per utilizzare la classe sun.misc.Unsafe v'è un metodo che proprio fa che: Il metodo

sun.misc.Unsafe.shouldBeInitialized(Class) 

rendimenti true se e solo se la Class fornito come parametro è (caricato ma) non inizializzato.

Problemi correlati