Разница между Java и другими языками заключается в том, что Java работает на виртуальной машине Java (JVM). Это означает, что скомпилированный код сохраняется в формате, независимом от платформы, а не в формате, который работает на конкретной машине. Этот формат имеет множество важных отличий от традиционного формата исполняемого кода. В частности, в отличие от программы C или C++, программа Java не является независимым исполняемым файлом, а состоит из множества отдельных файлов классов, каждый файл класса соответствует классу Java. Кроме того, эти файлы классов не загружаются в память сразу, а загружаются тогда, когда они нужны программе. Загрузчик классов — это инструмент, используемый в виртуальной машине Java для загрузки классов в память. Более того, загрузчик классов Java также реализован на Java. Таким образом, вы можете легко создать свой собственный загрузчик классов, не имея глубокого понимания виртуальной машины Java.
Зачем создавать загрузчик классов?
Теперь, когда в виртуальной машине Java уже есть загрузчик классов, нужно ли нам самим создавать другие? Хороший вопрос. Загрузчик классов по умолчанию знает, как загружать классы только из локальной системы. Когда ваша программа скомпилирована полностью в собственном коде, загрузчик классов по умолчанию обычно работает хорошо. Но одна из самых интересных особенностей Java — это то, насколько легко загружать классы из сети, а не просто локально.
Например, браузер может загружать классы через собственный загрузчик классов. Есть также много способов загрузки классов. Одна из самых интересных особенностей Java заключается в том, что ее можно настраивать не только локально, но и по сети:
* Автоматически проверять цифровые подписи перед выполнением ненадежного кода.
* Расшифровать код на основе пароля, предоставленного пользователем.
* Динамически создавайте классы в соответствии с потребностями пользователя. Все, что вам нужно, можно легко интегрировать в ваше приложение в виде байт-кода. Примеры пользовательских загрузчиков классов, если вы использовали JDK (Java Software Development Kit), appletviewer (браузер небольших приложений) или другой.
Для браузеров со встроенным Java вы уже используете собственный загрузчик классов. Когда Sun впервые выпустила язык Java, одним из самых интересных моментов было наблюдение за тем, как Java выполняет код, загруженный с удаленного веб-сайта. Выполнить с удаленного сайта через HTTP
Байт-код, передаваемый через P-соединение, выглядит немного странно. Это работает, потому что Java имеет возможность устанавливать собственные загрузчики классов. Браузер апплетов содержит загрузчик классов. Этот загрузчик классов не находит классы Java локально. Вместо этого он обращается к удаленному серверу, загружает исходный файл байт-кода через HTTP, а затем преобразует его в класс Java на виртуальной машине Java. Конечно, загрузчики классов делают много других вещей: они блокируют небезопасные классы Java и не позволяют различным апплетам на разных страницах мешать друг другу. Echidna, пакет, написанный Люком Горри, представляет собой открытый программный пакет Java, который позволяет безопасно запускать несколько приложений Java на виртуальной машине Java. Он предотвращает взаимодействие между приложениями за счет использования специального загрузчика классов, предоставляющего каждому приложению копию файла класса.
загрузчик классов Java:
По умолчанию в Java есть три загрузчика классов: загрузчик классов начальной загрузки, загрузчик классов расширения и загрузчик системных классов (также называемый загрузчиком классов приложений).
Загрузчики классов — одна из самых мощных функций Java. Но разработчики часто забывают загружать компоненты. Загрузчик классов — это класс, отвечающий за поиск и загрузку файлов классов во время выполнения. Java позволяет использовать различные загрузчики классов, даже собственные загрузчики классов.
Программы Java содержат множество файлов классов, каждый из которых соответствует одному классу Java. В отличие от статических программ C, эти файлы классов загружаются в память один раз, и их необходимо загружать в любое время. Именно это отличает загрузчики классов. Он получает независимые от платформы байт-коды из исходных файлов (обычно файлов .class или .jar), а затем загружает их в пространство памяти JVM, чтобы их можно было интерпретировать и выполнить. По умолчанию каждый класс приложения загружается с помощью java.lang.ClassLoader. Поскольку он может передаваться по наследству, его функциональность можно свободно расширять.
Пользовательский загрузчик классов
импортировать java.io.*;
импортировать java.net.*;
импортировать java.util.*;
импортировать java.lang.reflect.Method;
публичный класс CustomClassLoader расширяет URLClassLoader {
частный FileInputStream input = null //Поток ввода файла;
частный ByteArrayOutputStream out = null // поток вывода массива байтов;
Private String[] url = null //Путь загрузки файла класса;
Private byte[] data = null //Байт-код файла класса;
Private String ExtensionalName = "" //Расширение файла класса
public CustomClassLoader (URL[] URL) выдает исключение {
супер (URL-адреса);
this.url = новая строка[urls.length];
for (int i = 0; i <urls.length; i++) {
this.url[i] = urls[i].toURI().toString();
}
}
/*
* Анализ URL-адреса
*/
частный недействительный setFilePath() {
for (int i = 0; i < this.url.length; i++) {
if (this.url[i].substring(0,4).toLowerCase().equals("file") == true) {
this.url[i] = this.url[i].substring(5);
}
}
}
/*
* Получить байт-код файла с указанным именем класса (имя пакета + имя класса)
* @name имя Строка
* @return byte[]
*/
частный байт [] getFileData (имя строки) {
пытаться {
этот.setFilePath();
for (Строка URL: this.url) {
Строка fileName = URL + name.replace('.', '/').concat(".") +
this.getExtensionalName();
ввод = новый FileInputStream (новый файл (имя файла));
если (вход!= ноль) {
перерыв;
}
}
выход = новый ByteArrayOutputStream();
данные = новый байт[1024];
int len = -1;
while ((len = input.read(data)) != -1) {
out.write(данные, 0, длина);
}
данные = out.toByteArray();
} catch (Исключение е) {
е.printStackTrace();
} окончательно {
пытаться {
если (вход!= ноль)
ввод.закрыть();
если (выход != ноль)
выход.закрыть();
возврат данных;
} catch (Исключение е) {
е.printStackTrace();
вернуть ноль;
}
}
}
/*
* Поиск файлов классов по указанному имени класса.
* Имя @param Строка
* @return Класс
*/
защищенный класс findClassByName (имя строки) {
пытаться {
данные byte[] = this.getFileData(имя);
если (данные == ноль) {
вернуть ноль;
}
вернуть this.defineClass(имя, данные, 0, data.length);
} catch (Исключение е) {
е.printStackTrace();
вернуть ноль;
}
}
/*
* Переопределить метод loadClass()
* Имя @param Строка
* @return Класс
*/
общественный класс loadClass (имя строки) {
Класс c = ноль;
пытаться {
c = super.loadClass(имя);
} catch (ClassNotFoundException e) {
е.printStackTrace();
} окончательно {
if (c == null) //Когда метод родительского класса по умолчанию не загружен в указанный класс, используйте собственный метод, чтобы найти его
c = this.findClassByName(имя);
вернуть с;
}
}
публичная строка getExtensionalName() {
вернуть расширенное имя;
}
public void setExtensionalName (String ExtensionalName) {
this.extensionalName = ExtensionalName;
}
public static void main(String[] args) выдает исключение {
URL[] url = новый URL[] {новый URL("file:e:/")} //Добавьте путь к классу, который вы хотите загрузить.
//Может быть сетевым или локальным
CustomClassLoader csl = новый CustomClassLoader (url);
csl.setExtensionalName("rs");
Класс c1 = csl.loadClass("com.demo");
Объект obj = c1.newInstance();
Метод метод = c1.getMethod("printText", null);
метод.invoke(объект, ноль);
}