Когда JVM загружает классы? - PullRequest
19 голосов
/ 27 сентября 2011

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

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

Будет ли выполнение этой строки:

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

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

Ответы [ 3 ]

23 голосов
/ 27 сентября 2011

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

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) не приводит к загрузке класса, поскольку на самом деле вам не нужна никакая информация, это просто ссылка на объект.

РЕДАКТИРОВАТЬ: В вашем измененном вопросе вы спрашиваете, загружает ли класс 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 голосов
/ 27 сентября 2011

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

0 голосов
/ 27 сентября 2011

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

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

удачи.

...