2010-09-09 29 views
9

Będziesz prawdopodobnie zapytać, dlaczego miałbym to zrobić - to dlatego, że używam klasy (z zewnętrznej biblioteki), która robi rzeczy w statycznym inicjalizatorze i muszę wiedzieć, czy to się stało, czy nie.Jak sprawdzić, czy klasa została zainicjowana?

Spojrzałem na ClassLoader, ale nie znalazłem niczego, co wyglądałoby na użyteczne. Jakieś pomysły?

+1

masz na myśli "czy klasa jest inicjowana". jest ogromna różnica. – irreputable

+0

Dzięki za wskazanie tego. Zmieniłem tytuł. – mik01aj

+1

Którą bibliotekę? Być może istnieje efekt uboczny, który możesz sprawdzić (na przykład sterowniki JDBC rejestrują się w DriverManager). –

Odpowiedz

13

Można użyć metody ClassLoader.findLoadedClass(). Jeśli zwróci wartość null, klasa nie zostanie załadowana. W ten sposób nie ładujesz klasy, jeśli nie została jeszcze załadowana.


UWAGA: Ten kod naprawdę nie działa tu w classloader systemu findLoadedClass() jest chroniony, trzeba zastąpić go własnym ClassLoader.

zobacz link poniżej W tym samym temacie, by sprawdzić, czy klasa jest ładowany z classloader systemu

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

Bardzo dobry punkt z @irreputable:

"załadowany" nie oznacza "zainicjowany". inicjalizacji zdarza się tylko w ściśle określonych momentach JLS3 $ 12.4.1

Cytuję:

klasy lub interfejs typu T zostanie zainicjowany bezpośrednio przed pierwszym wystąpieniu jednego z następujących :

  • T jest klasa i instancją T jest tworzony.
  • T to klasa i metoda statyczna zadeklarowana przez T jest wywoływana.
  • Zostało przypisane pole statyczne zadeklarowane przez T.
  • Stosowane jest pole statyczne zadeklarowane jako T, a pole nie jest stałą zmienną (§4.12.4).
  • T to klasa najwyższego poziomu, i assert oświadczenie (§14.10) leksykalnie zagnieżdżone w T jest wykonywany.

Inwokacja niektórych metod w klasie Class odblaskowymi oraz w pakiecie java.lang.reflect powoduje również klasy lub interfejsu inicjalizacji. Klasa lub interfejs nie zostaną zainicjowane w żadnych innych okolicznościach.


Zasoby:

Na SA mi temat:

+0

Czy to nie spowoduje, że 'String' zostanie załadowany po wywołaniu metody, ponieważ ma on na celu oszacowanie' String' literal '" java.lang.String "'? –

+0

Cóż, kod tak naprawdę nie działa, nie możemy wywołać metody findLoadedClass() w domyślnym programie ładującym klasy. Rozważ to jako prosty przykład. –

+0

Jasne, wymyślny prosty przykład, ale czy twoje polecenie "if" zawsze będzie "prawdziwe"? –

4

Dlaczego po prostu nie odwołujesz się do klasy (tworząc odniesienie, tworząc instancję lub uzyskując dostęp do statycznego elementu)? To uruchomi inicjator typu, jeśli jeszcze nie został uruchomiony, a jeśli tak, to nadal jesteś gotowy.

+0

Ponieważ biblioteka ta odczytuje parametry za pomocą 'System.getProperty' i muszę wiedzieć, czy nadal mogę je zmienić. – mik01aj

2

można uzyskać JVM wydrukować zajęcia jak ładuje je, używając -verbose flagę. To może ci pomóc.

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, właśnie próbowałem na program Hello World i załadowany 309 klas wow!)

1

Można spróbować czegoś takiego:

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

+0

to nie działa, to na pewno zwróci wartość null. – irreputable

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

będzie blokować aż klasa została zainicjowana (sama lub jakiegoś innego wątku)

0

Jeśli jej nie zbyt późno .. To powinno zadziałać jak dobrze

Class.forName().newInstance(); 

newInstance() tworzy nową instancję klasy reprezentowanej przez ten obiekt klasy. Klasa jest tworzona tak, jakby była nowym wyrażeniem z pustą listą argumentów. Klasa zostanie zainicjowana, jeśli jeszcze nie została zainicjowana.

1

Wiem, że jest bardzo późno, ale myślę, że ta odpowiedź może być przydatna. Jeśli nie jesteś zbyt przestraszony (i są dozwolone), aby użyć klasy sun.misc.Unsafe istnieje metoda, która precyzyjnie robi: Metoda

sun.misc.Unsafe.shouldBeInitialized(Class) 

powraca true wtedy i tylko wtedy, gdy Class dostarczane jako parametru (załadowany, ale) nie zainicjowany.