Подтвердить что ты не робот

Как использовать URLClassLoader для загрузки файла *.class?

Я играю с Reflection, и я думал, что сделаю что-то, что загружает класс и печатает имена всех полей в классе. Я сделал небольшой класс приветствия мирового класса, чтобы что-то проверить:

[email protected]:~/eclipsews/SmallExample/bin$ ls
IndependentClass.class
[email protected]:~/eclipsews/SmallExample/bin$ java IndependentClass 
Hello! Goodbye!
[email protected]:~/eclipsews/SmallExample/bin$ pwd
/home/kent/eclipsews/SmallExample/bin
[email protected]:~/eclipsews/SmallExample/bin$ 

Исходя из вышеизложенного, я делаю два вывода:

  • Он существует в /home/kent/eclipsews/SmallExample/bin/IndependentClass.class
  • Это работает! (Так что это должен быть правильный .class файл, который может быть загружен загрузчиком класса)

Затем код, который должен использовать Reflection: (Линия, которая вызывает исключение, отмечена)

import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

public class InspectClass {
    @SuppressWarnings("unchecked")
    public static void main(String[] args) throws ClassNotFoundException, MalformedURLException {
        URL classUrl;
        classUrl = new URL("file:///home/kent/eclipsews/SmallExample/bin/IndependentClass.class");
        URL[] classUrls = { classUrl };
        URLClassLoader ucl = new URLClassLoader(classUrls);
        Class c = ucl.loadClass("IndependentClass"); // LINE 14
        for(Field f: c.getDeclaredFields()) {
            System.out.println("Field name" + f.getName());
        }
    }
}

Но когда я запускаю его, я получаю:

Exception in thread "main" java.lang.ClassNotFoundException: IndependentClass
    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:306)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
    at InspectClass.main(InspectClass.java:14)

Мои вопросы:

  • Что я делаю неправильно выше? Как это исправить?
  • Есть ли способ загрузить несколько файлов классов и перебрать их?
4b9b3361

Ответ 1

Из Javadocs для конструктора URLClassLoader(URL[]):

Создает новый URLClassLoader для указанных URL-адресов, используя родительский класс ClassLoader по умолчанию. URL-адреса будут найдены в порядке, указанном для классов и ресурсов после первого поиска в загрузчике родительского класса. Предполагается, что любой URL, который заканчивается на '/', ссылается на каталог. В противном случае предполагается, что URL-адрес относится к файлу JAR, который будет загружен и открыт по мере необходимости.

Итак, у вас есть два варианта:

  • Обратитесь к каталогу, в котором находится файл .class.
  • Поместите файл .class в JAR и обратитесь к этому

(1) в этом случае проще, но (2) может быть удобно, если вы используете сетевые ресурсы.

Ответ 2

Вы должны предоставить каталоги или файлы jar, содержащие ваши .class файлы, в URLClassLoader:

classUrl = new URL("file:///home/kent/eclipsews/SmallExample/bin/");

И да, вы можете загружать столько классов, сколько хотите

Ответ 3

Вы должны загрузить класс, указав полное имя класса, которое является именем класса, с его траекторией пакета, как

Class c = ucl.loadClass("com.mypackage.IndependentClass");

Ответ 4

У меня была аналогичная проблема, но мой файл класса находился внутри пакета с именем "customElements". В таких сценариях URL-адрес должен быть сконструирован до папки чуть выше корневого пакета, а в методе загрузки должно быть передано полное имя класса, включая пакет. Например, в моем случае; URL-адрес:

File customElementsDir = new File("D:/My Space");
//File customElementsDir = new File("D:\\customElements");
URL[] urls = null;
try {
    URL url = customElementsDir.toURI().toURL();
    urls = new URL[] { url };
} catch (MalformedURLException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

И фактическая загрузка была такой:

clazz = childFirstClassLoader
            .loadClass("customElements.CustomLoadableClass");

Где childFirstClassLoader - мой загрузчик классов.