Как проверить, инициализирован ли класс? - PullRequest
10 голосов
/ 09 сентября 2010

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

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

Ответы [ 7 ]

14 голосов
/ 09 сентября 2010

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


ПРЕДУПРЕЖДЕНИЕ : этот код не работает здесь, в системе ClassLoader, findLoadedClass() защищен, вам нужно переопределить его своим собственным ClassLoader.

Проверьте ссылку ниже В той же теме , чтобы проверить, загружен ли класс с помощью системы 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 также вызывают инициализацию класса или интерфейса.Класс или интерфейс не будут инициализированы ни при каких других обстоятельствах.


Ресурсы:

По той же теме:

4 голосов
/ 09 сентября 2010

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

2 голосов
/ 09 сентября 2010

Вы можете заставить 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 классов! Вау)

1 голос
/ 24 января 2018

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

sun.misc.Unsafe.shouldBeInitialized(Class)

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

1 голос
/ 09 сентября 2010

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

Класс c = новый ClassLoader () {Класс c = findLoadedClass (className); } .C;

0 голосов
/ 31 августа 2016

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

 Class.forName().newInstance();

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

0 голосов
/ 09 сентября 2010
Class.forName("com.abc.Xyz", true, this.getClass().getClassLoader())

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...