静态块与静态方法 - 初始化静态字段

时间:2011-11-18 21:36:21

标签: java static-methods static-members performance-testing

出于好奇,我测量了静态块和静态方法初始化器之间的性能。首先,我在两个独立的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);    
    }
}

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

之后,我写了this段代码来计算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 ;我还不懂字节码。

2 个答案:

答案 0 :(得分:2)

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

有关更多有趣信息,请参阅此有趣文章:Java Secret: Are static blocks interpreted?

答案 1 :(得分:2)

以下是我猜测的原因:

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

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

要测试这个,你可以尝试在你的java命令中添加-Xms200m或其他东西;这应该消除了在初始化期间垃圾收集的需要。