0

我正在尝试编写一个代码来编译和运行另一个java类,在它从一个字符串创建它之后。

我的问题是当我跑步时

    Class classToLoad = null;
    ClassLoader classLoader = Server.class.getClassLoader();
    try {
        classToLoad = classLoader.loadClass(className);
    } catch (Exception e) {
        e.printStackTrace();
    }

它抛出一个 ClassNotFoundException。我的问题不在于包,因为如果我调试代码并在“getClassLoader”之前放置一个断点并重新加载类,那么我的代码工作正常,它会看到最近在应用程序中创建的类。

如何在运行时重新加载类以便 loadClass 工作?

4

2 回答 2

1

看看这个教程

ClassLoader 加载/重新加载示例

... 让我们看一个简单的例子。下面是一个简单的 ClassLoader 子类的示例。注意它如何将类加载委托给它的父类,除了它打算能够重新加载的一个类。如果将此类的加载委托给父类加载器,则以后无法重新加载。请记住,一个类只能由同一个 ClassLoader 实例加载一次。

如前所述,这只是一个示例,用于向您展示 ClassLoader 行为的基础知识。它不是您自己的类加载器的生产就绪模板。您自己的类加载器可能不应该仅限于单个类,而是您知道需要重新加载的类的集合。此外,您可能也不应该对类路径进行硬编码。

public class MyClassLoader extends ClassLoader{

    public MyClassLoader(ClassLoader parent) {
        super(parent);
    }

    public Class loadClass(String name) throws ClassNotFoundException {
        if(!"reflection.MyObject".equals(name))
                return super.loadClass(name);

        try {
            String url = "file:C:/data/projects/tutorials/web/WEB-INF/" +
                            "classes/reflection/MyObject.class";
            URL myUrl = new URL(url);
            URLConnection connection = myUrl.openConnection();
            InputStream input = connection.getInputStream();
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            int data = input.read();

            while(data != -1){
                buffer.write(data);
                data = input.read();
            }

            input.close();

            byte[] classData = buffer.toByteArray();

            return defineClass("reflection.MyObject",
                    classData, 0, classData.length);

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

}

下面是一个使用 MyClassLoader 的示例。

public static void main(String[] args) throws
    ClassNotFoundException,
    IllegalAccessException,
    InstantiationException {

    ClassLoader parentClassLoader = MyClassLoader.class.getClassLoader();
    MyClassLoader classLoader = new MyClassLoader(parentClassLoader);
    Class myObjectClass = classLoader.loadClass("reflection.MyObject");

    AnInterface2       object1 =
            (AnInterface2) myObjectClass.newInstance();

    MyObjectSuperClass object2 =
            (MyObjectSuperClass) myObjectClass.newInstance();

    //create new class loader so classes can be reloaded.
    classLoader = new MyClassLoader(parentClassLoader);
    myObjectClass = classLoader.loadClass("reflection.MyObject");

    object1 = (AnInterface2)       myObjectClass.newInstance();
    object2 = (MyObjectSuperClass) myObjectClass.newInstance();

}
于 2015-08-30T14:00:41.453 回答
0

可能会问:“你加载类的上下文是什么?” 将有助于更好地回答您的问题。

大多数标准框架(如 Spring)在内部处理加载类并仅公开这些类提供的方法。

尝试Class.forName(String name)以尝试加载类并将句柄返回给类对象。

如果你想专门使用自己的类加载器来加载类,使用重载的:Class.forName(String name, boolean initialize, ClassLoader loader)

但是您需要确保您的类加载器能够找到要正确加载的类。

对于您正在使用的类加载器,请尝试: Thread.currentThread().getContextClassLoader()

于 2015-08-30T14:43:44.213 回答