为什么在 Java 中第一次调用方法会有 运行 的时间开销?

Why is there run time overhead on the first time a method is called in Java?

我正在测量我的代码的执行时间,并在第一次调用方法(从 main 方法)时发现了一些奇怪的行为。这是我的代码,请看看这个

public static void main(String[] args) {
    try (Scanner input = new Scanner(System.in)) {
        int iNum = input.nextInt();
        long lStartTime = System.nanoTime();

        // ***********(First call in main) Calling isPrime *************

        lStartTime = System.nanoTime();
        printResult(isPrime(iNum));
        System.out.println("Time Consumed in first call-: " 
                + (System.nanoTime() - lStartTime));

        // ***********(Second call in main) Calling isPrime *************
        lStartTime = System.nanoTime();
        printResult(isPrime(iNum));
        System.out.println("Time Consumed in second call-: "
                + (System.nanoTime() - lStartTime));
    }
}

private static boolean isPrime(int iNum) {
    boolean bResult = true;

    if (iNum <= 1 || iNum != 2 && iNum % 2 == 0) {
        bResult = false;
    } else {
        double iSqrt = Math.sqrt((double) iNum);
        for (int i = 3; i < iSqrt; i += 2) {
            if (iNum % i == 0) {
                bResult = false;
                break;
            }
        }
    }
    return bResult;
}

private static void printResult(boolean bResult) {
    if (bResult)
        System.out.println("\nIt's prime number.");
    else
        System.out.println("\nIt's not prime number.");
}

输入

5

输出

It's prime number.
Time Consumed in first call-: 484073

It's prime number.
Time Consumed in second call-: 40710

描述

上面我只描述了一个输入和输出的测试用例。但是,第一个方法调用和第二个方法调用之间的执行时间始终存在差异。

我也试过两种以上的方法调用方式类似,发现除了一个方法调用之外,其他调用之间并没有这么大的差异。除了第一个方法调用 484073ns[=30] 之外的其余调用,我在 40710ns 左右获得正确的执行时间(此执行时间在您的系统上可能不同) =].我很容易看到在第一个方法调用中有 484073 - 40710 = 443363ns(大约)的时间开销,但为什么会这样?根本原因是什么?

Java Runtime Environment 有多个实现,因此并非每个实现的行为都像 Oracle 的(以及以前的 Sun 的)。

开始表示,在 大多数 当前实现中,方法的初始调用涉及验证和 Java 字节码的第一遍编译。因此,该方法的后续调用会更快。但是,Java 也使用 JIT。维基百科在 Just-in-time compilation 上提供了一个条目,其中注释

JIT causes a slight delay to a noticeable delay in initial execution of an application, due to the time taken to load and compile the bytecode.

然后,继续说,

The application code is initially interpreted, but the JVM monitors which sequences of bytecode are frequently executed and translates them to machine code for direct execution on the hardware.