जैसा कि पहले ही बताया जा चुका है, अनावश्यक पुनरावृत्तियों को दूर करने के लिए जेआईटी ( जस्ट -इन-टाइम) कंपाइलर एक खाली लूप का अनुकूलन कर सकता है। पर कैसे?
दरअसल, दो JIT कंपाइलर हैं: C1 & C2 । सबसे पहले, कोड को C1 के साथ संकलित किया जाता है। C1 आंकड़े एकत्र करता है और JVM को यह पता लगाने में मदद करता है कि 100% मामलों में हमारा खाली लूप कुछ भी नहीं बदलता है और बेकार है। इस स्थिति में सी 2 चरण में प्रवेश करता है। जब कोड को बहुत बार कहा जाता है, तो इसे एकत्र आँकड़ों का उपयोग करके C2 के साथ अनुकूलित और संकलित किया जा सकता है।
एक उदाहरण के रूप में, मैं अगले कोड स्निपेट का परीक्षण करूंगा (मेरा JDK 9-आंतरिक निर्माण को धीमा करने के लिए सेट है ):
public class Demo {
private static void run() {
for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
}
System.out.println("Done!");
}
}
निम्नलिखित कमांड लाइन विकल्पों के साथ:
-XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*Demo.run
और मेरी रन विधि के विभिन्न संस्करण हैं , जो C1 और C2 के साथ उचित रूप से संकलित हैं। मेरे लिए, अंतिम संस्करण (C2) कुछ इस तरह दिखता है:
...
; 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
...
यह थोड़ा गड़बड़ है, लेकिन अगर आप बारीकी से देखते हैं, तो आप देख सकते हैं कि यहां कोई लंबे समय तक चलने वाला लूप नहीं है। 3 ब्लॉक हैं: बी 1, बी 2 और बी 3 और निष्पादन चरण B1 -> B2 -> B3
या हो सकते हैं B1 -> B3
। जहां Freq: 1
- एक ब्लॉक निष्पादन की सामान्यीकृत अनुमानित आवृत्ति।
javap -v
।