मैंने JVM specification को संकलन संकलन पर पढ़ा और स्ट्रिंग पर स्विच स्टेटमेंट संकलित करने में रुचि रखने में दिलचस्पी दिखाई। यहाँ परीक्षा पद्धति मैं जांच (JDK1.7.0_40) है:स्ट्रिंग संकलन को दो स्विच में स्विच क्यों करें
static int test(String i) {
switch (i) {
case "a": return -100;
case "45b": return 1;
case "c": return 2;
default: return -1;
}
}
मैं इस विधि स्ट्रिंग के hashCode पर सरल lookupswitch में संकलित होने की उम्मीद है, लेकिन अचानक
static int test(java.lang.String);
Code:
0: aload_0
1: astore_1
2: iconst_m1
3: istore_2
4: aload_1
5: invokevirtual #6 // Method java/lang/String.hashCode:()I
8: lookupswitch { // 3
97: 44
99: 72
51713: 58
default: 83
}
44: aload_1
45: ldc #7 // String a
47: invokevirtual #8 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
50: ifeq 83
53: iconst_0
54: istore_2
55: goto 83
58: aload_1
59: ldc #9 // String 45b
61: invokevirtual #8 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
64: ifeq 83
67: iconst_1
68: istore_2
69: goto 83
72: aload_1
73: ldc #10 // String c
75: invokevirtual #8 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
78: ifeq 83
81: iconst_2
82: istore_2
83: iload_2
84: tableswitch { // 0 to 2
0: 112
1: 115
2: 117
default: 119
}
112: bipush -100
114: ireturn
115: iconst_1
116: ireturn
117: iconst_2
118: ireturn
119: iconst_m1
120: ireturn
आप देख सकते हैं के रूप में, पहली लुकअपविच की शाखाओं में जेवीएम इसके बाद के बाद के टेबलविच (लाइन 84) के लिए वास्तविक उत्पन्न करने वाले इंडेक्स नहीं कर रहा है।
टेबल्सविच को तेजी से काम करना चाहिए ताकि बहुत अधिक काम नहीं मिल सके। लेकिन वैसे भी, अतिरिक्त स्विच उत्पन्न करने का उद्देश्य क्या है?
अद्यतन
मैं हैशकोड टकराव की संभावना को समझता हूं। मैं जो कहने की कोशिश कर रहा हूं वह यह है कि बाद के टेबलविच की बजाय, कंपाइलर सभी असली काम को बाद में टेबलविच से पहले स्थानांतरित कर सकता है और फिर सभी स्विच शाखाओं के अंत तक कूदने के लिए ifeq का उपयोग कर सकता है। तो एक संभावित उत्तर मैं यहां देखता हूं: कि पहले स्विच कंपाइलर में मामलों की ज्ञात संख्या के आधार पर ifeq कूद के लिए लेबल को प्रीकंप्यूट करने का प्रयास करता है, लेकिन मुझे यकीन नहीं है कि यह एकमात्र कारण है।
Update2
@ericbn के रूप में सुझाव दिया है, मैं के रूप में पूर्णांक और संकलक मुझे सादा lookupswitch दिया मैं के साथ
switch (i) {
case 97: return -100;
case 51713: return 1;
case 99: return 2;
default: return -1;
}
संकलन करने की कोशिश की।
विशिष्ट स्ट्रिंग (रों) कबूतर का घोंसला सिद्धांत के कारण एक ही hashCode हो सकता है। मुझे लगता है कि यही कारण है कि यह दो स्विच (एसएस) करता है। –
क्या आपको नहीं लगता कि केवल एक स्विच है? दूसरा स्विच सशर्त वापसी के लिए है। – HuStmpHrrr
@HuStmpHrrr दूसरा स्विच संकेत की स्पष्ट रूप से अप्रचलित परत पेश करता है, तालिका से देखा गया कूद जो पहले स्विच ब्लॉक में 'गोटो' लक्ष्य के रूप में गंभीर रूप से डाला जा सकता था। –