静态块vs静态方法 - 初始化静态域
问题描述:
出于好奇,我测量了静态块和静态方法初始值设定项之间的性能。首先,我实现上述方法在两个独立的Java类,像这样:静态块vs静态方法 - 初始化静态域
第一:
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;我还不懂字节码。
答
我认为为什么静态块版本慢于静态方法的版本可能是由于不同的JIT优化他们得到的原因...
看到这个有趣的文章更有趣的信息:Java Secret: Are static blocks interpreted?
答
这是我对此的猜测:
您正在做的初始化是创建足够多的对象,导致一个或多个垃圾回收。
当从静态块调用初始化时,它在类初始化期间完成,而不是在简单方法执行期间完成。在类初始化期间,即使堆的内容几乎相同,垃圾检测器可能还有更多工作要做(比如,执行堆栈比较长)。
为了测试这个,你可以尝试在你的java命令中加入-Xms200m或其他东西;这应该消除在你正在进行的初始化期间垃圾收集的需要。
尝试在调用批处理脚本时查看第一个和第二个查看结果是什么:) – antlersoft
指令的数量与这些指令需要多长时间无关(告诉您开车穿过城镇与全国各地 - 好吧,除非你住在Lichenstein或其他地方)。他们是完全一样的说明吗?我相当怀疑这一点。在附注中,即使速度更快,我也会犹豫是否使用第二个版本 - 它依赖于进行initList()调用,这是我永远不会指望的。 –
@antlersoft它返回相同的结果。已经测试过它。 – Mechkov