需要在运行时用动态生成和编译的java . class文件替换运行时中的现有类



我的目的是在运行时动态地向类定义注入新的属性和getter setter方法。目前,我有一个方法来重新生成的代码与新添加的属性,然后将编译生成的代码。

最初,我将在编译时为每个类创建一个模板。在运行项目时,模板类被加载到运行时。我编写了一些代码来动态生成java代码并对其进行编译。当我使用下面的代码加载新创建的类时,我无法访问注入的方法。我认为我无法覆盖现有的运行时定义。我浏览了很多博客,但仍然不明白为什么。请帮助。

我正在访问DROOLS中新添加的方法,并且它没有在任何其他类中引用,这可能会在编译期间引发问题。带有新属性的规则引擎的规则在运行时更新,因此我需要相应地调整我的代码。下面是ClassLoader代码。这段代码没有抛出任何异常,但未能解决我的目的。不确定编码是否正确。

public static boolean loadClass2RunTime() {
    try {
        File folder = new File("target");
        File dir = new File(folder, "com/itap/template");
        File[] classFiles = dir.listFiles();
        URL[] url = new URL[] { folder.toURI().toURL() };
        int i = 0;
        for (File classFile : classFiles) {
            if (classFile.getName().matches(".*\.class")) {
                System.out.println(classFile.getName().substring(0,
                        classFile.getName().lastIndexOf(".")));
                ClassLoader loader = URLClassLoader
                        .newInstance(new URL[] { folder.toURI().toURL() });
                Class cls = loader.loadClass("com.itap.template."
                        + classFile.getName().substring(0,
                                classFile.getName().lastIndexOf(".")));
                ClassLoader temp = cls.getClassLoader();
            }
        }
        return true;
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (MalformedURLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return false;
}

URLClassLoader在需要在运行时加载新生成的类时非常有用。不幸的是,您将无法使用URLCLassLoader重新加载已经加载的类的定义(即重新加载一个类)。

当我使用下面的代码加载新创建的类时,我不是能够访问注入的方法。我想我不能重写现有运行时定义。

URLClassLoader将检查指定的类是否已经加载。如果找到,它只返回指向已加载类的实例。因此,您将无法覆盖现有的运行时定义。

解决方案:在Java中,支持动态类重载的标准方法是读取类的字节信息(从它的.class文件中),并编写一个自定义类加载器来使用这些字节信息加载类。

使用自定义ClassLoader时要记住的要点:

  • 要重新加载一个类,现有的ClassLoader实例(它加载了类)和所有加载的类实例都应该被垃圾收集。
  • Custom ClassLoader必须只加载特定的类(需要加载/重新加载)。加载所有其他类(内置Java类或来自其他包的类)的请求必须委托给它的父类加载器。尝试加载内置系统类可能会导致特权异常。

类装入器在装入类时遵循的步骤如下:

  1. 检查类是否已经加载。
  2. 如果没有加载,请求父类加载器加载类。
  3. 如果父类加载器不能加载类,尝试在这个类加载器中加载它。

当你实现一个能够重新加载类的类加载器时,你需要稍微偏离这个顺序。类重新加载请求不应该委托给父类加载器。

下面是示例链接,可以帮助您在Java中开发自定义类加载器。http://www.javablogging.com/java-classloader-2-write-your-own-classloader/
http://tutorials.jenkov.com/java-reflection/dynamic-class-loading-reloading.html

评论后编辑:

我认为语句InputStream stream =.getClassLoader getClass () () .getResourceAsStream(名称);的示例中的loadClassData函数没有获取最新的类的版本。

你是对的,它没有选择类的最新版本,仅仅是因为它使用现有的ClassLoader来获取流(指向你的类的旧版本)。

你可以用

FileInputStream stream = new FileInputStream("Path to your class file");
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int data = stream.read();
while(data != -1){
    buffer.write(data);
    data = stream.read();
}
stream.close();
byte[] classData = buffer.toByteArray();

读取类的字节信息,并尝试使用您的ClassLoader版本(自定义ClassLoader)加载它。

相关内容

  • 没有找到相关文章

最新更新