2014-10-10 49 views
1

我在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();  
    } 
} 

回答

0

的问题是,对于ClassLoader.loadClassClass.forName正常行为是,如果它以前加载返回现有Class。他们不会查看类文件以查看它是否已更改。基本上,Java中的对象类型的身份相当于由类的完全限定名和其类加载器组成的元组,这意味着JVM不能(也不会不是)允许类加载器“定义”两个具有相同名称的类,如果试图做到这一点,我认为defineClass方法将会让您回到以前加载的类的Class对象。)

所以...

为了实现您正在尝试实现的目标,您需要每次创建一个新的ClassLoader 你想加载一个新版本的类。

+0

谢谢!目前,我正在使用FileServer的ClassLoader来加载所有的类,所以每次我想要加载新版本的类时,您是否可以提供关于如何创建新的ClassLoader的更多提示?并且这是否意味着每次我编译一个文件,我只需要在类已经加载之前创建一个新的ClassLoader? – emmaBYP 2014-10-10 06:07:06