处理需要编译多个源文件( .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
的其他选择?
或者更好或更快的方式进行运行时编译和类文件生成?
我不能使用多线程,因为环境是单线程的。
答案 0 :(得分:1)
无需一次一个地编译源文件。您可以一次性编译所有这些内容(只需将它们全部放在String[]
中)。
这会快得多,因为大部分时间花在初始化事情上,而且只花了一小部分来编译源文件。
Say - 作为估计 - 在编译源文件上花费0.2秒,在初始化时花费1.8秒。然后编译2000个文件需要1.8 + 2000 * 0.2 = 401.8秒。这只是猜测;当你尝试真实时,它可能会有所不同。
您可能还想检查源文件自上次编译后是否实际发生了更改,并且只有在至少其中一个文件发生更改时才会再次编译。
在等待上述猜测时,更容易证明等待 - 在代码实际发生变化时启动时间为7分钟,而不是没有。
答案 1 :(得分: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。
答案 2 :(得分: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:我没有测试过,但你可以试试。