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

标签 java classloader

我正在编写一个应用程序,需要在运行时重新加载先前加载的类。原因是该类是在运行时自动生成的,并且新的实现改变了应用程序的工作方式。我只生成该类的一个对象,并将其从所有依赖项中剥离,只保留一个定义常量值的接口(interface)。重新加载时重置任何或所有成员的值都没有问题。我确切地知道它什么时候发生变化并且我可以控制它。我遇到的唯一问题是重新加载本身。

根据我的阅读,我应该使用类加载器。我尝试这样做,但无法成功。

我尝试了以下方法:

  • 获取当前的 ClassLoader (myClassObject.getClass().getClassLoader()) 并使用它重新加载类 - 不起作用。它可能会继续加载旧的实现。
  • 生成我自己的(又名从 SO 复制粘贴并进行修改)- 不起作用,因为我生成的 ClassLoader 与生成该类的 ClassLoader 不同(异常(exception):myClass 无法转换为 myClass)。
  • 创建一个设置父类(super class)的 ClassLoader 的构造函数似乎没有任何效果。
  • 使用我的新 ClassLoader 生成以 myClassObject 作为成员的类,解决了 myClassObject 的 ClassLoader 不匹配问题,但在上一级创建了一个新的不匹配问题。我每次都使用 getClassLoader() ,但发现它们不匹配。
  • 我尝试添加 -Djava.system.class.loader=com.test.Reoader com.test.myMainClass 以使其成为我的默认重新加载器,但编译器出现错误。
  • Google 不断将我指向我已经读过的相同内容。
  • 编辑:我尝试创建一个接口(interface)并重新加载实现它的类。这也没有解决问题。

我知道我应该重写默认的类加载器,但我所做的一切似乎都没有成功。

我的类加载器:

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;
    }
}

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

最佳答案

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

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

关于java - 如何重新加载先前加载的在运行时更改的类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16618225/

相关文章:

java - 如何使用所有四个节点连接到cassandra数据库

java - Class.isAssignableFrom 在某些情况下会给出错误的结果

java - 在 Tomcat Servlet 中调用时,getAnnotations() 不返回 "external"注释

java - 我得到一个 "exception in thread "main"java.lang.NoClassDefFoundError : org/openqa/selenium/WebDriver"

java - Wildfly 和 Mybatis 存在延迟加载异常

java - JDBC中如何调用存储过程

java - 使用java从aws lambda中的/tmp目录写入然后读取文件

java - 创建一个随机方法,将对象添加到具有随机索引的堆栈中

java - 如何防止代币替换攻击?

java - 单个 JVM 中不同线程上的两个不同版本的 jar