Java 动态地重新编译和重新加载类

Java 动态地重新编译和重新加载类,java,java-compiler-api,dynamic-class-loaders,reloading,Java,Java Compiler Api,Dynamic Class Loaders,Reloading,我正在用java构建一个可以接收java源文件的服务器,它应该使用JavaCompiler动态编译它,然后加载该类。但是问题是,如果服务器接收到一个名称相同但内容不同的文件,它仍然会加载上一个类并给出相同的输出。我注意到一些答案建议为我试图加载的类创建一个超类,并使用另一个类加载器,但是如果java源文件被动态发送到服务器,情况是否仍然如此 以下是我在FileServer.java中的编译和加载方法: public final static int FILE_SIZE = 1022386; p

我正在用java构建一个可以接收java源文件的服务器,它应该使用JavaCompiler动态编译它,然后加载该类。但是问题是,如果服务器接收到一个名称相同但内容不同的文件,它仍然会加载上一个类并给出相同的输出。我注意到一些答案建议为我试图加载的类创建一个超类,并使用另一个类加载器,但是如果java源文件被动态发送到服务器,情况是否仍然如此

以下是我在FileServer.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();     
    }
}
public final static int FILE_SIZE=1022386;
公共静态void编译(字符串文件名)
{
//将源代码保存在.java文件中。
文件源文件=新文件(文件名);
//编译源文件。
JavaCompiler=ToolProvider.getSystemJavaCompiler();
诊断收集器诊断=
新诊断收集器();
StandardJavaFileManager文件管理器=
编译器.getStandardFileManager(诊断,null,null);
File[]files=新文件[]{sourceFile};
Iterable cls=Class.forName(className);
Class cls=classLoader.loadClass(className);
方法meth=cls.getMethod(“main”,String[].class);
字符串[]params=null;
方法调用(空,(对象)参数);
}捕获(例外e){
e、 printStackTrace();
}
}

问题在于
ClassLoader.loadClass
Class.forName
的正常行为是返回先前加载的现有
类。他们不会查看类文件以查看它是否已更改

(这有一个很好的理由。基本上,Java中对象类型的标识相当于一个元组,由类的完全限定名及其类加载器组成。这意味着JVM不能(也不会)允许类加载器“定义”两个名称相同的类。如果您尝试实现此操作,我认为
defineClass
方法将返回先前加载的类的
Class
对象。)

所以


为了实现您想要实现的目标,您需要在每次加载新版本的类时创建一个新的类加载器。

谢谢!目前,我正在使用FileServer的类加载器来加载所有的类,所以每次我想加载一个新版本的类时,您能否给出更多关于如何创建新类加载器的提示?这是否意味着每次编译一个文件时,我都需要创建一个新的类加载器,前提是该类以前已经加载过?