Daha önce de belirtildiği gibi, JIT (tam zamanında) derleyicisi, gereksiz yinelemeleri kaldırmak için boş bir döngüyü optimize edebilir. Ama nasıl?
Aslında, iki JIT derleyicisi vardır: C1 ve C2 . İlk olarak, kod C1 ile derlenir. C1 istatistikleri toplar ve JVM'nin% 100 durumlarda boş döngümüzün hiçbir şeyi değiştirmediğini ve faydasız olduğunu keşfetmesine yardımcı olur. Bu durumda C2 sahneye girer. Kod çok sık arandığında, toplanan istatistikler kullanılarak C2 ile optimize edilebilir ve derlenebilir.
Örnek olarak, sonraki kod parçacığını test edeceğim ( JDK'm slowdebug build 9-internal olarak ayarlandı ):
public class Demo {
private static void run() {
for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
}
System.out.println("Done!");
}
}
Aşağıdaki komut satırı seçenekleriyle:
-XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*Demo.run
Ve çalıştırma yöntemimin C1 ve C2 ile uygun şekilde derlenmiş farklı versiyonları var . Benim için son değişken (C2) şuna benzer:
...
; B1: # B3 B2 <- BLOCK HEAD IS JUNK Freq: 1
0x00000000125461b0: mov dword ptr [rsp+0ffffffffffff7000h], eax
0x00000000125461b7: push rbp
0x00000000125461b8: sub rsp, 40h
0x00000000125461bc: mov ebp, dword ptr [rdx]
0x00000000125461be: mov rcx, rdx
0x00000000125461c1: mov r10, 57fbc220h
0x00000000125461cb: call indirect r10 ; *iload_1
0x00000000125461ce: cmp ebp, 7fffffffh ; 7fffffff => 2147483647
0x00000000125461d4: jnl 125461dbh ; jump if not less
; B2: # B3 <- B1 Freq: 0.999999
0x00000000125461d6: mov ebp, 7fffffffh ; *if_icmpge
; B3: # N44 <- B1 B2 Freq: 1
0x00000000125461db: mov edx, 0ffffff5dh
0x0000000012837d60: nop
0x0000000012837d61: nop
0x0000000012837d62: nop
0x0000000012837d63: call 0ae86fa0h
...
Biraz dağınık, ancak yakından bakarsanız, burada uzun süren bir döngü olmadığını fark edebilirsiniz. 3 blok vardır: B1, B2 ve B3 ve yürütme adımları B1 -> B2 -> B3
veya olabilir B1 -> B3
. Nerede Freq: 1
- bir blok yürütmenin normalleştirilmiş tahmini sıklığı.
javap -v
görmek için ile inceleyin.