提问者:小点点

如何测量JVM启动时间?


我有一个用java编写的应用程序,我想知道在到达静态空int main(String args)之前需要多少时间,以及它在该阶段正在做什么,我如何实现它?

我知道微软有一个名为MPGO(经理配置文件引导优化)的工具,Java有等效工具吗?


共3个答案

匿名用户

从Java应用程序内部测量启动时间的简单方法:

import java.lang.management.ManagementFactory;

public class Test {

    public static void main(String[] args) {
        long currentTime = System.currentTimeMillis();
        long vmStartTime = ManagementFactory.getRuntimeMXBean().getStartTime();
        System.out.println(currentTime - vmStartTime);
    }
}

您可以使用JVMTI代理来跟踪VM事件,如类加载、垃圾收集、方法编译等。这里是我制作的一个简单代理-vmtrace(以及编译后的Windows dll)。

运行java-agentpath:path\to\vmtrace.dll Main,事件跟踪将打印到stderr

[0.00000] VMTrace started
[0.00182] Dynamic code generated: flush_icache_stub
[0.00187] Dynamic code generated: get_cpu_info_stub
[0.00519] Dynamic code generated: getCPUIDNameInfo_stub
[0.00524] Dynamic code generated: forward exception
[0.00526] Dynamic code generated: call_stub
...
[0.01182] Loading class: java/lang/Object
[0.01198] Loading class: java/lang/String
[0.01206] Loading class: java/io/Serializable
...
[0.05620] VM initialized
[0.05664] Class prepared: java/lang/invoke/MethodHandle
[0.05672] Loading class: java/lang/invoke/MethodHandleImpl
[0.05732] Class prepared: java/lang/invoke/MethodHandleImpl
[0.05738] Loading class: java/lang/invoke/MethodHandleImpl$1
[0.05743] Class prepared: java/lang/invoke/MethodHandleImpl$1
[0.05755] Loading class: java/lang/invoke/MethodHandleImpl$2
[0.05759] Loading class: java/util/function/Function
[0.05768] Class prepared: java/util/function/Function
...

匿名用户

在 java 9 中,您可以添加 -Xlog:class init=info:file=trace.log 来跟踪类初始化(这是类加载后的下一步),然后过滤主类。这是一项新的日志记录功能。

您还可以告诉它记录所有内容以查看启动前发生的情况,但记录的事件量可能会扭曲结果。

在 java 8 及更低版本中,不同的 VM 组件有自己的日志记录(通常只是通过 printf),并且类加载不包含时间戳。

匿名用户

测量启动时间的另一种方法是使用自Java9起可用的ProcessHandle:

public static void main(String[] args) {
    var currentTimeMillis = System.currentTimeMillis();
    var processStartTime = ProcessHandle.current().info().startInstant().get();
    System.out.println(currentTimeMillis - processStartTime.toEpochMilli());
}