如何重新加载在运行时更改的以前加载的类?

时间:2013-05-17 21:31:18

标签: java classloader

我正在编写一个需要在运行时重新加载以前加载的类的应用程序。原因是该类在运行时自动生成,新实现改变了应用程序的工作方式。我只生成所述类的一个对象,并且我从所有依赖项中删除它,但是一个定义常量值的接口。重新加载时重置任何或所有成员的值都没有问题。我知道它何时发生变化,我可以控制它。我唯一的问题是重装本身。

根据我的阅读,我应该使用ClassLoader。我试图这样做,但我不能让它发挥作用。

我尝试了以下内容:

  • 获取当前的ClassLoader(myClassObject.getClass().getClassLoader())并使用它来重新加载类 - 不起作用。它可能会继续加载旧的实现。
  • 生成我自己的(带有修改的SO的AKA复制粘贴) - 不起作用,因为我生成的ClassLoader与生成类的ClassLoader不同(例外:myClass不能转换为myClass)。
  • 创建一个设置超类ClassLoader的构造函数似乎没有任何效果。
  • 使用我的新ClassLoader生成myClassObject作为成员的类解决了myClassObject的ClassLoader不匹配问题,但创建了一个新级别不匹配的错误。我每次都使用getClassLoader(),但我发现它们不匹配。
  • 我尝试添加-Djava.system.class.loader=com.test.Reoader com.test.myMainClass以使其成为默认的重新加载器,但我从编译器中收到错误。
  • 谷歌一直指着我已经读过的东西。
  • 编辑:我尝试创建一个界面并重新加载实现它的类。这也没有解决它。

我知道我应该覆盖默认的ClassLoader,但我所做的一切似乎都没有成功。

我的ClassLoader:

public class Reloader extends ClassLoader {

    public Reloader(){
        super(Reloader.class.getClassLoader());
    }

    @Override
    public Class<?> loadClass(String s) {
        return findClass(s);
    }

    @Override
    public Class<?> findClass(String s) {
        try {
            byte[] bytes = loadClassData(s);
            return defineClass(s, bytes, 0, bytes.length);
        } catch (IOException ioe) {
            try {
                return super.loadClass(s);
            } catch (ClassNotFoundException ignore) {}
            ioe.printStackTrace(java.lang.System.out);
            return null;
        }
    }

    private byte[] loadClassData(String className) throws IOException {
        File f = new File("out\\production\\ManoCPU\\" + className.replaceAll("\\.", "/") + ".class");
        int size = (int) f.length();
        byte buff[] = new byte[size];
        FileInputStream fis = new FileInputStream(f);
        DataInputStream dis = new DataInputStream(fis);
        dis.readFully(buff);
        dis.close();
        return buff;
    }
}

非常感谢任何可以提供帮助的人。

1 个答案:

答案 0 :(得分:1)

您只能加载一次类(每个类加载器的实例)。这意味着您必须丢弃已加载类的类加载器,并为更新版本的类实例化一个新的加载器。

当处理多个类加载器时,还要记住,如果使用多个类加载器加载相同的类,则它们不会被识别为同一个类。