偶尔对 Java 源文件进行轻微修改,例如一些额外的显式转换,以帮助编译器将单个 java 文件的编译时间从 4 分钟缩短到 3 秒(尤其是在 Java 8 中)。
问题是:在大型 java 项目中,您如何找到哪些特定的 .java 文件编译缓慢?
有没有办法让 Ant 计算编译每个单独的 .java 文件需要多长时间?
最佳答案
我认为这是可能的。这是我发现的:
如果您使用的是 Java 8,您可以注册一个 Plugin与编译器一起在编译期间添加一些额外的功能。该文档对插件有这样的说法:
It is expected that a typical plug-in will simply register a TaskListener to be informed of events during the execution of the compilation, and that the rest of the work will be done by the task listener.
因此您可以设置一个插件来使用 TaskListener,并在生成类时让任务监听器记录时间戳。
package xyz;
import com.sun.source.util.JavacTask;
import com.sun.source.util.Plugin;
public class TimestampPlugin implements Plugin {
@Override
public String getName() {
return "Timestamp_Plugin";
}
@Override
public void init(JavacTask task, String... strings) {
task.setTaskListener(new FileTimestampListener());
}
}
Documentation for TaskListener .任务监听器被传递给一个 TaskEvent ,它有一个 Kind .就您而言,听起来您对生成感兴趣。
package xyz;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskListener;
import java.util.HashMap;
public class FileTimestampListener implements TaskListener {
HashMap<String, Long> timeStampMap = new HashMap<>();
@Override
public void started(TaskEvent taskEvent) {
if(TaskEvent.Kind.GENERATE.equals(taskEvent.getKind())) {
String name = taskEvent.getSourceFile().getName();
timeStampMap.put(name, System.currentTimeMillis());
}
}
@Override
public void finished(TaskEvent taskEvent) {
if(TaskEvent.Kind.GENERATE.equals(taskEvent.getKind())) {
String name = taskEvent.getSourceFile().getName();
System.out.println("Generated " + name + " over " + (System.currentTimeMillis() - timeStampMap.get(name)) + " milliseconds");
}
}
}
这是一个简单的例子,但从这里开始设置类似日志文件的东西来存储收集的信息应该很简单。正如您在插件的 init 函数中看到的那样,参数可以从命令行传递给插件。
插件通过使用-Xplugin 编译器参数指定来配置。我不确定为什么,但似乎没有关于 this page 的任何文档关于它,但它可以通过在 META-INF/services 目录中设置一个名为 com.sun.source.util.Plugin 的文件(要实现的接口(interface)的 FQ 类名)来使用。所以:
META-INF
|-- services
|-- com.sun.source.util.Plugin
并在该文件中列出您实现此类的 FQ 类名。所以文件内容将是:
xyz.TimestampPlugin
在您的 Ant 任务中,您只需要指定一个编译器标志 -Xplugin:Timestamp_Plugin(注意这是插件的 getName() 函数提供的名称)。您还需要在类路径或注释处理器路径(如果指定的话)上提供已编译的插件和运行时依赖项。
关于java - 计时每个文件用 ant 编译需要多长时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36538716/