#java #classloader #urlclassloader
#java #загрузчик классов #urlclassloader
Вопрос:
Мое приложение использует стандартный набор инструментов виджетов (SWT) для своего графического интерфейса. Моя проблема в том, что 32-разрядная библиотека SWT не работает на 64-разрядной JVM. Но я не хочу заставлять людей выбирать правильную архитектуру при получении программного обеспечения. Итак, я хочу объединить обе 32-разрядные и 64-разрядные библиотеки и автоматически определять архитектуру во время выполнения. Я обнаружил, что могу получить правильную архитектуру JVM следующим образом:
if (System.getProperty("os.arch").contains("64")) {
// ...
}
Теперь все, что осталось, это загрузить jar. Но проблема в том, что все примеры, которые я нашел, требуют, чтобы вы вручную загружали класс перед его использованием.
Class.forName("MyClass", false, myClassLoader);
Итак, мой вопрос в том, возможно ли «зарегистрировать» мой загрузчик классов, чтобы мне не приходилось загружать классы заранее?
Обновление: я создал свой собственный дочерний класс URLClassLoader
и установил его в качестве загрузчика классов по умолчанию с аргументом командной строки -Djava.system.class.loader
; но я получаю эту ошибку:
Error occurred during initialization of VM
java.lang.Error: java.lang.NoSuchMethodException: com.program.LibraryLoader.<init>(java.lang.ClassLoader)
at java.lang.ClassLoader.initSystemClassLoader(Unknown Source)
at java.lang.ClassLoader.getSystemClassLoader(Unknown Source)
Я думаю, LibraryLoader.<init>
относится к конструктору… но он есть ( public LibraryLoader(URI[] urls)
).
Обновление 2: Почти готово, JVM запускается сейчас. Я добавил этот конструктор, чтобы заставить его работать:
public LibraryLoader(ClassLoader classLoader) {
super(new URL[0], classLoader);
}
Но после добавления jar с помощью addPath()
( file:lib/jars/swt.jar
) он выдает только NoClassDefFoundError
. Да, я дважды проверил, существует ли файл.
Ответ №1:
Вы могли бы попытаться внедрить свой пользовательский загрузчик классов с помощью свойства «java.system.class.loader» (см. ClassLoader#getSystemClassLoader). Тем не менее, я бы рекомендовал использовать OSGi и позволить фреймворку выполнять сложные задачи.
Комментарии:
1. Если я введу его с помощью
java.system.class.loader
, будут ли другие классы по-прежнему загружены по умолчаниюClassLoader
?2. Вам нужно будет убедиться, что ваш собственный загрузчик классов делегирует его родительскому для любого класса, отличного от swt.
3. Хорошо, я нашел здесь еще немного информации: coderanch.com/t/384068/java/java/Adding-JAR-file-Classpath-at . Как мне установить это свойство (
java.system.class.loader
) перед запуском программы?4. Вы можете задать системное свойство, добавив следующий аргумент командной строки: -Djava.system.class.loader=com.mycompany. MyClassLoader . Обратите внимание, что этот аргумент должен быть установлен перед вашими собственными аргументами программы (если таковые имеются), но после содержимого Xmx / Xms.
5. Могу ли я установить это в МАНИФЕСТЕ? Если да, то каким образом?
Ответ №2:
Как часть конструктора для вашего пользовательского загрузчика классов, вызовите definePackage с соответствующей информацией, с URL-адресом, указывающим на желаемый файл jar.
Этот пример показывает, что пользовательский загрузчик классов вызывается, когда я пытаюсь создать экземпляр класса из swing, потому что я определил свой загрузчик классов как загрузчик этого пакета.
import java.net.URL;
public class junk extends ClassLoader {
byte[] dummy = new byte[0];
public static void main(String[] args) throws Exception {
new junk();
new javax.swing.JPanel();
}
public junk() throws Exception {
definePackage("javax.swing","","","","","","",new URL("file://junk.class"));
}
public Class<?> findClass(String s) throws java.lang.ClassNotFoundException{
Class<?> retVal = super.findClass(s);
System.out.println("delegated responsibility for " s " to superclass");
return retVal;
}
public Package getPackage(String s) {
Package retVal = super.getPackage(s);
System.out.println("delegated responsibility for " s " to superclass");
return retVal;
}
}
Результат:
делегированная ответственность за javax.swing для суперкласса