为什么我的班级不重新加载?

时间:2009-12-25 18:47:40

标签: java

我知道我遗漏了一些基本的东西。我正在尝试动态编译一个类,然后在更改后重新加载它。以下代码有效。但是,当我调用它两次(更改.java后一次)时,类定义不会更新。我错过了什么?

File file = new File("/eraseme/Eraseme.java");
File[] files = new File[] {file};
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();           
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects(files);
CompilationTask task = compiler.getTask(null, fileManager, null, null,null,compilationUnits);
boolean madeIt = task.call(); // works

File classFile = new File("/eraseme/Eraseme.class");
URL url = classFile.toURL();
URL[] urls = new URL[] { url };
ClassLoader cl = new URLClassLoader(urls);      
Class cls = cl.loadClass("Eraseme");
TestApi test = (TestApi) cls.newInstance();
System.out.println(test.getVersion());

1 个答案:

答案 0 :(得分:2)

您遗漏的是传递给URLClassLoader的网址应该是搜索到的目录。发生的事情是你正在构建的URLClassLoader实际上并没有找到.class文件,但是找不到类并且正在回到让父类加载器加载类。

具体来说,尝试将代码的第二位修改为:

File classFile = new File("/eraseme");
URL url = classFile.toURL();
URL[] urls = new URL[] { url };
ClassLoader cl = new URLClassLoader(urls);      
Class cls = cl.loadClass("Eraseme");  // will try to load /eraseme/Eraseme.class
TestApi test = (TestApi) cls.newInstance();
System.out.println(test.getVersion());

请注意,如果您的类(包含)com.mycompany.erasestuff.EraseMe被调用,则类加载器将查找文件/eraseme/com/mycompany/erasestuff/EraseMe.class

请注意,执行此操作时,您不希望系统类加载器能够加载EraseMe类。系统类加载器优先,您的URLClassloader不会加载任何内容。 (不幸的是,当你对类加载器说“加载这个类”时,首先检查它的父类加载器是否可以加载该类,然后它会尝试自己加载它。如果系统类加载器可以加载这个类,你永远不会得到不同的版本)