Подтвердить что ты не робот

Когда загружаются классы JVM?

Предположим, что у меня есть следующий класс:

class Caller {
  public void createSomething() {
    new Something();
  }
}

Выполняет эту строку:

static void main() {
   Class<?> clazz = Caller.class;
}

заставляет JVM загружать класс Something или загрузка класса отложена до тех пор, пока не будет вызван метод createSomething()?

4b9b3361

Ответ 1

Класс загружается только тогда, когда вам требуется информация об этом классе.

public class SomethingCaller {
    public static Something something = null; // (1) does not cause class loading
    public static Class<?> somethingClass = Something.class; // (2) causes class loading

    public void doSomething() {
        new Something(); // (3) causes class loading
    }
}

Линии (2) и (3) вызовут загрузку класса. Объект Something.class содержит информацию (строка (2)), которая может быть получена только из определения класса, поэтому вам нужно загрузить класс. Для вызова конструктора (3), очевидно, требуется определение класса. Аналогично для любого другого метода в классе.

Однако строка (1) не вызывает загрузку класса, поскольку на самом деле вам не нужна какая-либо информация, это просто ссылка на объект.

EDIT: в вашем измененном вопросе вы спрашиваете, ссылается ли на Something.class класс. Да. Он не загружает класс до тех пор, пока не будет выполнено main(). Используя следующий код:

public class SomethingTest {
    public static void main(String[] args) {
        new SomethingCaller();
    }
}

public class SomethingCaller {
    public void doSomething() {
        Class<?> somethingClass = Something.class;
    }
}

public class Something {}

Этот код не вызывает загрузку Something.class. Однако, если я вызываю doSomething(), класс загружается. Чтобы проверить это, создайте вышеуказанные классы, скомпилируйте их и удалите файл Something.class. Вышеупомянутый код не сбой с ClassNotFoundException.

Ответ 2

Да, это вызовет загрузку класса при загрузке класса, содержащего ссылку File.class. Единственный способ не делать этого - ссылаться на класс путем отражения. Затем вы можете управлять им при загрузке.

Ответ 3

Если у вас есть требования к производительности, это строгое, вам следует рассмотреть возможность создания пользовательского объекта ClassLoader. Это позволит вам выгружать классы из памяти, когда они больше не нужны.

Вам нужно проверить методы loadClass, findClass и, возможно, defineClass в классе ClassLoader, переопределить нагрузку и найти и использовать defineClass в реализации. Поиск Google при написании пользовательских загрузчиков классов покажет много примеров кода для этого, но в основном вы собираетесь кэшировать результаты класса в Map (имя класса для класса), а затем предоставить некоторый механизм обратного вызова для удаления загруженных классов из вашего кеша когда они не нужны.

удачи.