8

出于好奇,我测量了静态块和静态方法初始化器之间的性能。首先,我在两个单独的 java 类中实现了上述方法,如下所示:

第一的:

class Dummy {
    static java.util.List<Integer> lista = new java.util.ArrayList<Integer>();
    static {
        for(int i=0; i < 1000000; ++i) {
            lista.add(new Integer(i));
        }
    }
}

public class First {
    public static void main(String[] args) { 
        long st = System.currentTimeMillis();
            Dummy d = new Dummy();
        long end = System.currentTimeMillis() - st;
        System.out.println(end);    
    }
}

第二:

class Muddy {
    static java.util.List<Integer> lista = new java.util.ArrayList<Integer>();
    public static void initList() {
        for(int i=0; i < 1000000; ++i) {
            lista.add(new Integer(i));
        }
    }
}

public class Second {
    public static void main(String[] args) { 
        long st = System.currentTimeMillis();
            Muddy.initList();
            Muddy m = new Muddy();
        long end = System.currentTimeMillis() - st;
        System.out.println(end);    
    }
}

然后我执行了这个小批处理脚本来测量它 100 次并将值放入一个文件中。batchFile.bat First Second dum.res.txt

之后,我编写了这段代码来计算 Dummy 和 Muddy 测量值的平均值和标准偏差。

这是我得到的结果:

First size: 100 Second size: 100
First       Sum: 132    Std. deviation: 13
Second      Sum: 112    Std. deviation: 9

它在我的其他机器上也很相似......每次我测试它。

现在我想知道,为什么会这样?我检查了字节码,Second.class 在调用 System.currentTimeMillis() 之间多了一条指令(调用静态 initList())。他们都做同样的事情,但为什么第一个慢?我不能仅仅通过查看字节码来推断它,因为这是我第一次接触javap;我还不明白字节码。

4

2 回答 2

2

我认为静态块版本比静态方法版本慢的原因可能是由于他们获得了不同的 JIT 优化......

有关更多有趣信息,请参阅这篇有趣的文章:Java 秘密:是否解释了静态块?

于 2011-11-18T22:16:31.307 回答
2

以下是我对此原因的猜测:

您正在进行的初始化是创建足够的对象,从而导致一个或多个垃圾回收。

当从静态块调用初始化时,它是在类初始化期间完成的,而不是在简单方法执行期间完成的。在类初始化期间,垃圾检测器可能比在简单方法执行期间有更多的工作要做(例如,因为执行堆栈更长),即使堆的内容几乎相同。

要对此进行测试,您可以尝试在您的 java 命令中添加 -Xms200m 或其他内容;这应该消除您在初始化期间进行垃圾收集的需要。

于 2011-11-18T22:21:25.293 回答