Seperti yang telah ditunjukkan, kompiler JIT (just-in-time) dapat mengoptimalkan loop kosong untuk menghapus iterasi yang tidak perlu. Tapi bagaimana caranya?
Sebenarnya, ada dua kompiler JIT: C1 & C2 . Pertama, kode dikompilasi dengan C1. C1 mengumpulkan statistik dan membantu JVM menemukan bahwa dalam 100% kasus loop kosong kami tidak mengubah apa pun dan tidak berguna. Dalam situasi ini C2 memasuki panggung. Ketika kode sangat sering dipanggil, itu dapat dioptimalkan dan dikompilasi dengan C2 menggunakan statistik yang dikumpulkan.
Sebagai contoh, saya akan menguji cuplikan kode berikutnya (JDK saya disetel ke slowdebug build 9-internal ):
public class Demo {
private static void run() {
for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
}
System.out.println("Done!");
}
}
Dengan opsi baris perintah berikut:
-XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*Demo.run
Dan ada versi berbeda dari metode run saya , dikompilasi dengan C1 dan C2 secara tepat. Bagi saya, varian terakhir (C2) terlihat seperti ini:
...
; 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
...
Ini sedikit berantakan, tetapi jika Anda melihat lebih dekat, Anda mungkin memperhatikan bahwa tidak ada putaran panjang di sini. Ada 3 blok: B1, B2 dan B3 dan langkah-langkah pelaksanaannya bisaB1 -> B2 -> B3
atau B1 -> B3
. Dimana Freq: 1
- frekuensi perkiraan yang dinormalisasi dari eksekusi blok.
javap -v
untuk melihat.