计算每个文件用ant编译的时间

cli*_*nux 12 java ant javac

偶尔会对Java源文件稍作修改,例如一些额外的显式强制转换,以帮助编译器将单个java文件的编译时间从4分钟提高到3秒(特别是在Java 8中).

问题是:在一个大型java项目中,如何找到哪些特定的.java文件正在慢慢编译?

有没有办法让Ant有时间编译每个.java文件需要多长时间?

hei*_*don 4

我认为这可能是可能的。这是我发现的:

如果您使用的是 Java 8,则可以向编译器注册插件,以在编译期间添加一些附加功能。该文档对插件有这样的说法:

预计典型的插件将简单地注册一个 TaskListener 以在编译执行期间接收事件通知,其余工作将由任务侦听器完成。

因此,您可以设置一个插件来使用 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());
    }
}
Run Code Online (Sandbox Code Playgroud)

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");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个简单的示例,但从这里开始应该可以直接设置日志文件之类的东西来存储收集的信息。正如您在插件的 init 函数中看到的,可以从命令行将参数传递给插件。

该插件是通过使用-Xplugin编译器参数指定来配置的。我不确定为什么,但此页面上似乎没有任何关于它的文档,但可以通过设置一个名为 com.sun.source.util.Plugin 的文件(接口的 FQ 类名称)来使用它实施)在您的 META-INF/services 目录中。所以:

META-INF
|-- services
    |-- com.sun.source.util.Plugin
Run Code Online (Sandbox Code Playgroud)

并在该文件中列出该类的实现的 FQ 类名。所以文件内容将是:

xyz.TimestampPlugin
Run Code Online (Sandbox Code Playgroud)

在 Ant 任务中,您只需要指定编译器标志-Xplugin:Timestamp_Plugin(注意这是插件的 getName() 函数提供的名称)。您还需要在类路径或注释处理器路径(如果指定了)上提供已编译的插件和运行时依赖项。