JIT触发器多次执行某段代码后。
HotSpot JVM将尝试识别代码中的“热点”。热点是您执行很多次代码的部分。为此,JVM将“计数”各种指令的执行情况,当它确定某个片段频繁执行时,它将触发JIT。 (这是一个近似值,但这很容易理解)。 JIT(Just-In-Time)接受这段代码,并试图使其更快。
使用的JIT,使你的代码运行速度更快的技术有很多,但最常见的造成混乱的一个是:
- 它将尝试以确定是否那块代码使用的变量没有用在其他地方(无用的变量),并删除它们。
- 如果您获取和同一锁多次释放(如调用同一个对象的synchronized方法),它可以一次性获得锁定,如果你访问对象的成员做一个synchronized块
- 所有来电那些没有被声明为volatile的,它可以决定优化它(在寄存器和类似的地方放置值),在多线程代码中创建奇怪的结果。
- 它会内联方法,以避免通话费用。
- 它会将字节码转换为机器码。
- 如果循环完全无用,它可能会被完全删除。
所以,你的问题的正确答案是,被JITed后的空循环,没有时间执行..最有可能不存在了。
同样,还有很多其他的优化,但根据我的经验,这些是最令人头痛的问题。此外,JIT在任何新版本的Java中都得到了改进,有时它甚至会根据平台而有所不同(因为它在某种程度上是平台特定的)。由JIT完成的优化难以理解,因为即使在最近的Java版本中,这些优化中的某些优化已直接移至编译器中,您通常无法使用javap查找它们并检查字节码(例如,自从Java 6编译器能够检测和警告未使用的局部变量和私有方法)。
如果您正在编写一些循环来测试某些内容,通常是将循环放入方法中,在计时之前调用该方法几次以使其“加速”,然后执行定时循环。
这通常会触发在你们这样一个简单的程序的JIT,即使不能保证它确实会触发(或者说,它甚至存在于一定的平台)。
如果你想得到关于JIT或非JIT时间的偏执(我做过):做第一轮,计算每个执行循环的时间,并等待时间稳定(例如,与平均值的差值小于10 %),然后从“真实”时间开始。
我认为'System.nanoTime()'更是为这个测试表明(客户端/服务器的虚拟机也应该做一些差异) –
是啊,没错,毫秒往往过于粗粒度。 –