Динамическая загрузка классов не выполняется во время выполнения - PullRequest
3 голосов
/ 22 мая 2010

У меня есть следующий фрагмент кода Java:

final Class<?> junitCoreClass = AccessController.doPrivileged(
    new PrivilegedAction<URLClassLoader>() {
      @Override
      public URLClassLoader run() {
        return new URLClassLoader(new URL[] { junitJarUrl });
      }
    }).loadClass("org.junit.runner.JUnitCore");

System.out.println(junitCoreClass.getName());
final JUnitCore junitCore = (JUnitCore) junitCoreClass.newInstance();

Это прекрасно компилируется.Но когда я пытаюсь запустить его, происходит нечто странное;java.lang.NoClassDefFoundError добавляется в последнюю строку, ссылаясь на только что загруженный класс.Странная часть: println печатает точное имя класса.

Я проверил, что если я сохраню ссылку на новый экземпляр как Object и манипулирую ею только с помощью отражения, то все в порядке, поэтому оскорбительная частькода должен быть явным приведением.

Может ли кто-нибудь объяснить мне, почему это происходит, а также рассказать, как мне добиться того, что я пытаюсь сделать?

PS: Для тех, кто хочет увидеть более близкую трассировку стека, показать особо нечего:

java.lang.NoClassDefFoundError: org/junit/runner/JUnitCore
  at [last line of example)
  [lines from my app]
Caused by: java.lang.ClassNotFoundException: org.junit.runner.JUnitCore
  at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
  at java.security.AccessController.doPrivileged(Native Method)
  at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
  at java.lang.ClassLoader.loadClass(ClassLoader.java:315)
  at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:330)
  at java.lang.ClassLoader.loadClass(ClassLoader.java:250)
  at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:398)
  at [last line of example]
  [lines from my app]

Ответы [ 2 ]

4 голосов
/ 22 мая 2010

Проблема в том, что ваш основной класс загружается загрузчиком системных классов (тот, который содержит -classpath), у которого нет JUnit в пути к классам. Затем вы создаете отдельный загрузчик классов, в котором только путь JUnit. Когда ваш основной класс пытается привести к JUnitCore, загрузчику системного класса предлагается загрузить JUnitCore, которого он не содержит, поэтому происходит NoClassDefFoundError.

Нет удобного способа сделать то, что вы пытаетесь сделать, без использования отражения. Вам необходимо (1) создать отдельный класс, который напрямую обращается к JUnitCore, (2) включить путь к этому классу в URLClassLoader (каталог или JAR), (3) использовать отражение для загрузки этого класса и (4) использовать отражение для вызовите метод этого класса.

0 голосов
/ 22 мая 2010

Вам не нужно либо делать .loadClass("org.junit.runner.JUnitCore", **true**);, либо вызывать resolClass () для объекта класса перед созданием новых экземпляров?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...