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

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

第一:

class Dummy { static java.util.List lista = new java.util.ArrayList(); 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 lista = new java.util.ArrayList(); 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 ; 我还不懂字节码。

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

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

这是我猜测的原因:

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

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

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