Компилятор Java преобразует исходные инструкции в понятный для виртуальной машины Java код. Этот код сохраняется в файле класса с расширением .class. В каждом файле класса содержится код определения и реализации для только одного класса или интерфейса.
Далее все эти файлы классов интерпретируются программой, которая умеет преобразовывать набор инструкций виртуальной машины в машинные команды используемого компьютера.
Учтите, что интерпретатор виртуальной машины загружает только те файлы классов, которые необходимы для выполнения программы в данный момент.
Допустим, что выполнение программы начинается с файла MyProgram.class. Ниже описаны действия, которые выполняет виртуальная машина Java.
- В виртуальной машине имеется механизм загрузки файлов классов, например, путем считывания их с диска или копирования по сети. С помощью этого механизма загружается содержимое файла класса MyProgram.
- Если в классе MyProgram встречаются поля или объекты, ссылающиеся на классы других типов, тогда также еще загружаются и файлы этих классов. Процесс загрузки всех классов, от которых зависит данный класс, называется разрешением(resolving) класса.
- Затем виртуальная машина выполняет метод main() класса MyProgram. Этот метод является статическим, поэтому никаких экземпляров класса MyProgram создавать не требуется.
- Если для работы метода main() или метода, вызывающего из main(), требуются дополнительные классы, то загружаются соответствующие им файлы.
Следует отметить, что механизм загрузки классов использует не один, а несколько загрузчиков. С каждой программой Java применяется, по крайней мере, три загрузчика классов:
- первичный загрузчик классов(bootstrap class loader);
- расширенный загрузчик классов(extension class loader);
- системный загрузчик классов(system class loader), иногда называемый прикладным загрузчиком классов(application class loader).
Первичный загрузчик классов загружает системные классы, как правило, из файла rt.jar. Он является неотъемлемой частью виртуальной машины и обычно реализуется на языке Си.
Первичному загрузчику классов не соответствует ни одного объекта ClassLoader. Например, показанный ниже вызов возвращает значение null:
1 |
String.class.getClassLoader(); |
Расширенный загрузчик классов загружает стандартное расширение из каталога jre/lib/ext. Если переместить файлы .jar в этот каталог, то расширенный загрузчик классов найдет в нем нужные классы расширения даже без указания пути к классам. Некоторые специалисты рекомендуют применять этот механизм, чтобы избежать путаницы с указанием пути к классам, но такой способ связан с определенными сложностями, которые описаны ниже.
Системный загрузчик классов загружает прикладные классы, которые размещаются в каталогах и файлах формата JAR/ZIP. Путь к классам должен быть указан с помощью переменной окружения CLASSPATH или параметра командной строки — classpath.
В системе, реализованной компанией Sun, расширенный и системный загрузчик реализуются на языке Java. Оба они представляют собой экземпляры класса URLClassLoader.
Помещать библиотеки в каталог jre/lib/ext нежелательно по следующей причине. Предположим, что вам понадобился один из классов этой библиотеки, который, в свою очередь, должен загружать класс, не являющийся системным или расширенным. Расширенный загрузчик классов не использует информация о пути к классам, устанавливаемую в переменной окружения CLASSPATH.
Этот факт необходимо учитывать, принимая решения об использовании каталога jre/lib/ext в качестве хранилища для своих классов.
Помимо всех уже перечисленных мест, классы еще также могут загружаться и из каталога jre/lib/endorsed. Такой механизм может применяться только для замены определенных стандартных библиотек Java. Подробнее об этом можете узнать по адресу http://java.sun.com/javase/6/docs/technotes/guides/standards/index.html