2015-11-06 67 views
0

正在編譯需要編譯幾個源文件(.java)的應用程序,並在運行時生成相應的類文件(.class),這發生在應用程序啓動時。Java運行時編譯和類文件生成

目前使用以下代碼類生成:

int errorCode = com.sun.tools.javac.Main.compile(new String[] { 
     "-cp", classPath, 
     "-d", pOutputPath, 
     srcFile.getAbsolutePath() },new PrintWriter(out)); 

每* java文件幾乎沒有與單個方法中的一些40行代碼。但是上面給出的代碼需要編譯的時間大約是每個文件2秒

應用程序有超過1000或有時2000個java文件。所以應用程序啓動時間超過2000或4000秒,這是不可取的。

com.sun.tools.javac.Main.compile的任何替代方法?

或者更好或更快的方式進行運行時編譯和類文件生成?

我不能使用多線程,因爲環境是單線程的。

+0

你不能使用'CachedThreadPool'和消防作業來編譯文件嗎? – TheLostMind

+0

實際上,單個線程正在迭代目錄和編譯中的文件。如果我有多個線程,那麼我需要有很多線程安全措施,比如鎖定,同步等。尋找更快的Main.compile的替代方案。 –

+0

您真的需要在每次啓動時編譯類嗎? –

回答

0

最近,我使用ToolProvider在類似情況下:javax.tools.ToolProvider.getSystemJavaCompiler()

實施例:

protected static boolean compileFiles(List<String> additionalOptions,ArrayList<String> sources){ 
    JavaCompiler compiler=ToolProvider.getSystemJavaCompiler(); 
    if (compiler == null) return false; 
    StandardJavaFileManager fileManager=compiler.getStandardFileManager(null,null,null); 
    List<String> options=new ArrayList<String>(); 
    options.add("-d"); 
    options.add(getOutBuildDir().getAbsolutePath()); 
    options.add("-s"); 
    options.add(getOutSrcDir().getAbsolutePath()); 
    options.add("-verbose"); 
    if (additionalOptions != null) options.addAll(additionalOptions); 
    Iterable<? extends JavaFileObject> compilationUnits=fileManager.getJavaFileObjectsFromStrings(sources); 
    CompilationTask task=compiler.getTask(mOutputWriter,fileManager,null,options,null,compilationUnits); 
    return task.call(); 
} 

從這裏:http://www.programcreek.com/java-api-examples/javax.tools.ToolProvider

的另一種方法在運行時編譯是在存儲器編譯使用例如JIMCy圖書館(https://github.com/Krever/JIMCy)。它實際上是用Scala編寫的,但有Java API。

+0

這當然是調用Java編譯器的更好方法(但除非您也做其他事情,否則不會更快)。然而,目前這只是一個鏈接的答案,並且鏈接在一段時間後過時了。請包括相關信息並將其寫入您自己的答案中。 –

0

爲什麼不讓操作系統爲您處理?

我不知道這個,但我認爲你可以嘗試這樣的:

String path = "srcFolderPath"; 
File dir = new File(path); 
for (File src : dir.listFiles()) { 

    try { 
     ProcessBuilder pb = new ProcessBuilder() 
       .directory(dir.getAbsoluteFile()) 
       .command("javac " + src.getName()); // or whatever command params 

     Process p = pb.start(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

} 

PS:我沒有測試過,但你可以試試。

+0

你爲什麼認爲這樣更快? –

+0

@ErwinBolwidt我沒有,我只說OP可以試試它... –

1

沒有必要一次性編譯源文件。你可以一次編譯所有這些文件(只需把它們全部放在你的String[]中)。

那會快很多,因爲大部分兩秒都花在初始化的東西,只有一小部分是花在編譯源文件。

說 - 作爲一個估計 - 編譯源文件花費0.2秒,初始化東西1.8秒。然後編譯2000個文件需要1.8 + 2000 * 0.2 = 401.8秒。這只是一個猜測;它可能會有所不同,當你嘗試它是真實的。

而且您可能還想檢查源文件自上次編譯它們以來是否真的發生了更改,並且只有當其中至少一個已更改時纔再次編譯。

這是很容易證明等待 - 給出了上述猜想 - 第7分鐘,啓動時出現的代碼時相比,沒有實際變化。

+0

沒有編譯器需要0.2秒來編譯單個源文件。我爲一種語言編寫了一個編譯器,它的功能比Java要好得多,它需要0.3秒來完成初始化,每個源文件需要大約10毫秒。 – Clashsoft

+0

@Clashsoft是的,我寫了一個java編譯器。我在這裏提出一個建議,如何計算這個;因爲OP說編譯1個源文件需要2秒,所以編譯一個源文件需要0.31秒的例子顯然不適用。當然,持續時間取決於源文件的長度/複雜度,計算機速度等。 –