Как проверить, инициализирован ли класс?

вы, вероятно, спросите, почему я хочу это сделать-это потому, что я использую класс (из внешней библиотеки), который делает вещи в своем статическом инициализаторе, и мне нужно знать, было ли это сделано или нет.

Я посмотрел на ClassLoader, но не нашел ничего полезного. Есть идеи?

7 ответов


можно использовать ClassLoader.findLoadedClass() метод. Если он возвращает null, то класс не загружается. Таким образом, вы не загружаете класс, если он еще не был загружен.


предупреждение: этот код на самом деле не работает здесь, в загрузчике системных классов, findLoadedClass() защищена, вы должны заменить его своим загрузчиком.

Проверьте ссылку ниже по теме чтобы проверить, загружен ли класс системой ClassLoader

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

очень хороший момент от @irreputable:

" загружен "не означает"инициализирован". инициализация происходит только в точные моменты, определенные JLS3 $12.4.1

цитирую :

класс или тип интерфейса T будет инициализирован непосредственно перед первым появлением любого из следующих:

  • T - это класс и экземпляр T это.
  • T является классом и статическим методом, объявленным T вызывается.
  • статическое поле, объявленное T назначена.
  • статическое поле, объявленное T и поле не является постоянной переменной (§4.12.4).
  • T является классом верхнего уровня и assert заявление (§14.10) лексически вложенные в теги T выполняется.

вызов определенных отражающих методов в классе Class и в пакет java.lang.reflect также вызывает инициализацию класса или интерфейса. Класс или интерфейс не будут инициализированы ни при каких других обстоятельствах.


ресурсы :

по теме :


Почему бы вам просто не ссылаться на класс (путем создания ссылки, создания экземпляра или доступа к статическому члену)? Это запустит инициализатор типа, если он еще не запущен, и если он есть, то вам все еще хорошо идти.


вы можете заставить JVM распечатывать классы по мере их загрузки, используя флаг-verbose. Это может вам помочь.

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]

(кстати, просто попробовал это в программе Hello World, и он загрузил 309 классов! вау)


вы можете попробовать что-то вроде этого:

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


Я знаю, что уже очень поздно, но я думаю, что этот ответ может быть полезен. Если вы не слишком напуганы (и разрешается) использовать sun.misc.Unsafe class существует метод, который точно это: метод

sun.misc.Unsafe.shouldBeInitialized(Class)

возвращает true, если и только если Class при условии, что параметр (загружен, но) не инициализирован.


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

он будет блокировать, пока класс не будет инициализирован (сам по себе или какой-либо другой поток)


Если это не слишком поздно.. Это должно работать хорошо, а

 Class.forName().newInstance();

на newInstance() создает новый экземпляр класса, представленного этим Class объект. Экземпляр класса создается как бы новым выражением с пустым списком аргументов. Класс инициализируется, если он еще не был инициализирован.