2014-10-10 124 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