2015-11-06 66 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秒的例子显然不适用。当然,持续时间取决于源文件的长度/复杂度,计算机速度等。 –