Как использовать URLClassLoader для загрузки файла * .class? - PullRequest
29 голосов
/ 10 апреля 2009

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

kent@rat:~/eclipsews/SmallExample/bin$ ls
IndependentClass.class
kent@rat:~/eclipsews/SmallExample/bin$ java IndependentClass 
Hello! Goodbye!
kent@rat:~/eclipsews/SmallExample/bin$ pwd
/home/kent/eclipsews/SmallExample/bin
kent@rat:~/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)

Мои вопросы:

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

Ответы [ 4 ]

38 голосов
/ 10 апреля 2009

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

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

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

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

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

10 голосов
/ 10 апреля 2009

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

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

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

6 голосов
/ 08 июня 2012

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

Class c = ucl.loadClass("com.mypackage.IndependentClass");
0 голосов
/ 19 мая 2010

У меня была похожая проблема, но мой файл класса находился в пакете с именем "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 - мой загрузчик классов.

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