На лету класс загрузки с банками - PullRequest
0 голосов
/ 28 сентября 2010

У меня есть класс расширения ClassLoader с помощью следующего метода

@Override
public Class<?> findClass(String className) throws ClassNotFoundException {
    try {
        /**
        * Get a bytecode from file
        */

        byte b[] = fetchClassFromFS(pathtobin + File.separator
            + className.replaceAll("\\.", escapeSeparator(File.separator)) + ".class");
        return defineClass(className, b, 0, b.length);
    } catch (FileNotFoundException ex) {
        return super.findClass(className);
    } catch (IOException ex) {
        return super.findClass(className);
    }
}

Это, как вы можете видеть, использует метод defineClass () от его родителя - ClassLoader. Проблема в том, что когда я пытаюсь выполнить класс »(я получаю с моим расширением ClassLoader - пусть это будет ru.xmppTesting.test.Disco) метод getMethods () при получении экземпляра этого класса я получаю следующее

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/http/Header
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
    at java.lang.Class.privateGetPublicMethods(Unknown Source)
    at java.lang.Class.getMethods(Unknown Source)
    at DOTGraphCreator.createGraphFromClasses(DOTGraphCreator.java:85)
    at DOTGraphCreator.generateDotGraphFile(DOTGraphCreator.java:56)
    at DOTGraphCreator.main(DOTGraphCreator.java:46)
Caused by: java.lang.ClassNotFoundException: org.apache.http.Header
    at java.lang.ClassLoader.findClass(Unknown Source)
    at SourceClassLoader.findClass(SourceClassLoader.java:27)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    ... 7 more

Насколько я вижу, это потому, что класс org.apache.http.Header не может быть найден как определено. Потому что это не так.

Итак, вот вопрос:

как я могу и должен определить и связать этот класс Header (и множество других из моих .jar libs) вместе с определением ru.xmppTesting.test.Disco и другими подобными для их определения на лету?

1 Ответ

0 голосов
/ 28 сентября 2010

Если вы импортируете org.apache.http.Header из динамически загруженного класса, вам нужно, чтобы он был доступен для вашего classpath.

Если вы не хотите загружатьвсе потенциально необходимые фляги на вашем пути к классам, вы можете попробовать взломать, который я нашел здесь :

import java.lang.reflect.*;
import java.io.*;
import java.net.*;

public class ClassPathHacker {

private static final Class[] parameters = new Class[]{URL.class};

public static void addFile(String s) throws IOException {
    File f = new File(s);
    addFile(f);
}//end method

public static void addFile(File f) throws IOException {
    addURL(f.toURL());
}//end method


public static void addURL(URL u) throws IOException {

    URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader();
    Class sysclass = URLClassLoader.class;

    try {
        Method method = sysclass.getDeclaredMethod("addURL",parameters);
        method.setAccessible(true);
        method.invoke(sysloader,new Object[]{ u });
    } catch (Throwable t) {
        t.printStackTrace();
        throw new IOException("Error, could not add URL to system classloader");
    }//end try catch

}//end method

}//end class

Но, я должен сказать, он не мог быть переносим для некоторых JVM (не всегда SystemClassLoader является подклассом URLClassLoader) ...

* РЕДАКТИРОВАТЬ: * Фактически, поскольку вы заменили загрузчик классов своим собственным, возможно, у вас есть некоторые проблемы ...

...