java动态地重新编译和重新加载类
我正在用java构建一个可以接收java源文件的服务器,它应该使用JavaCompiler动态编译它,然后加载该类。但是问题是,如果服务器接收到一个名称相同但内容不同的文件,它仍然会加载上一个类并给出相同的输出。我注意到一些答案建议为我试图加载的类创建一个超类,并使用另一个类加载器,但是如果java源文件被动态发送到服务器,情况是否仍然如此
下面是我在文件服务器中的编译和加载方法。爪哇:
public final static int FILE_SIZE = 1022386;
public static void compile(String fileName)
{
// Save source in .java file.
File sourceFile = new File(fileName);
// Compile source file.
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector <JavaFileObject> diagnostics =
new DiagnosticCollector<JavaFileObject>();
StandardJavaFileManager fileManager =
compiler.getStandardFileManager(diagnostics, null, null);
File [] files = new File [] {sourceFile};
Iterable<? extends JavaFileObject> compilationUnits =
fileManager.getJavaFileObjectsFromFiles(Arrays.asList(files));
String [] compileOptions = new String[] {"-classpath", "runtime.jar"};
Iterable<String> compilationOptions = Arrays.asList(compileOptions);
JavaCompiler.CompilationTask task =
compiler.getTask(null, fileManager, diagnostics, compilationOptions,
null, compilationUnits);
task.call();
}
public static void compileLoad (String fileName)
{
compile(fileName);
String className = "";
int i = 0;
while(fileName.charAt(i) != '.') {
className += fileName.charAt(i);
i++;
}
ClassLoader classLoader = FileServer.class.getClassLoader();
// Dynamically load class and invoke its main method.
try {
//Class<?> cls = Class.forName(className);
Class<?> cls = classLoader.loadClass(className);
Method meth = cls.getMethod("main", String[].class);
String[] params = null;
meth.invoke(null, (Object) params);
} catch (Exception e) {
e.printStackTrace();
}
}
# 1 楼答案
问题是
ClassLoader.loadClass
或Class.forName
的正常行为是返回一个已加载的现有Class
。他们不会查看类文件以查看它是否已更改(这有一个很好的理由。基本上,Java中对象类型的标识相当于一个元组,由类的完全限定名及其类加载器组成。这意味着JVM不能(也不会)允许类加载器“定义”两个同名的类。如果您试图实现这一点,我认为
defineClass
方法将返回之前加载的类的Class
对象。)所以
为了实现您想要实现的目标,每次您想要加载一个新版本的类时,您都需要创建一个新的类加载器