Java: автоматический пользовательский загрузчик классов - PullRequest
1 голос
/ 27 апреля 2011

Мое приложение использует Standard Widget Toolkit (SWT) для своего графического интерфейса. Моя проблема в том, что 32-битная библиотека SWT не работает на 64-битной JVM. Но я не хочу, чтобы люди выбирали правильную архитектуру при получении программного обеспечения. Итак, я хочу объединить и 32-битные и 64-битные библиотеки и автоматически определять архитектуру во время выполнения. Я узнал, что могу получить правильную архитектуру JVM следующим образом:

if (System.getProperty("os.arch").contains("64")) {
    // ...
}

Теперь осталось только загрузить банку. Но проблема в том, что все примеры, которые я нашел, требуют, чтобы вы вручную загрузили класс перед его использованием.

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);
}

Но после добавления банок с addPath() (file:lib/jars/swt.jar) он выдает только NoClassDefFoundError. Да, я дважды проверил, что файл существует.

Ответы [ 2 ]

1 голос
/ 27 апреля 2011

Вы можете попытаться добавить свой пользовательский загрузчик классов с помощью свойства "java.system.class.loader" (см. ClassLoader # getSystemClassLoader). Однако я бы порекомендовал использовать OSGi и позволить фреймворку делать сложные вещи.

0 голосов
/ 27 апреля 2011

Как часть конструктора для вашего пользовательского ClassLoader, вызовите 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 суперклассу

...