0

处理需要编译多个源文件(.java)并在运行时生成相应的类文件( .class)的应用程序,这发生在应用程序启动时。

目前使用以下代码进行类生成:

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吗?

还是一种更好或更快的运行时编译和类文件生成方式?

我不能使用多线程,因为环境是单线程的。

4

3 回答 3

1

无需一次编译一个源文件。您可以一次性编译所有这些(只需将它们全部放入您的String[].

这会快得多,因为两秒钟的大部分时间都花在了初始化上,而只有一小部分花在了编译源文件上。

假设 - 作为估计 - 编译源文件花费 0.2 秒,初始化事物花费 1.8 秒。然后编译 2000 个文件需要 1.8 + 2000 * 0.2 = 401.8 秒。这只是一个猜测;当您真正尝试时,它可能会有所不同。

而且您可能还想检查自上次编译它们以来源文件是否确实发生了变化,并且只有在其中至少一个发生变化时才再次编译。

证明等待的合理性要容易得多——考虑到上面的猜测——当代码发生实际变化时比没有发生变化时启动 7 分钟。

于 2015-11-06T07:15:33.023 回答
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:我没有测试过,你可以试试。

于 2015-11-06T06:35:23.723 回答
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。

于 2015-11-06T06:26:38.233 回答