2012-03-31 8 views
7

निम्न जावा कोड निम्न JVM बाइटकोड उत्पन्न करता है।सिंक्रनाइज़ ब्लॉक में अप्रत्याशित कोड

मुझे उत्सुकता है कि 31 ऑफसेट से कोड 36 ऑफसेट करने के लिए क्यों उत्पन्न होता है। जेएलएस 7 या जेवीएम 7 विनिर्देशन में कुछ भी इस बारे में बात नहीं करता है। क्या मैं कुछ भूल गया?

भले ही मैं println स्टेटमेंट को हटा दूं, कोड (36 ऑफसेट करने के लिए ऑफसेट 31) अभी भी पहले के स्थान पर उत्पन्न हो गया है, क्योंकि प्रिंटल कॉल हटा दिया गया है।

// Java code 
    void testMonitor() { 
     Boolean x = new Boolean(false); 
     synchronized(x) { 
      System.out.println("inside synchronized"); 
      System.out.println("blah"); 
     }; 
     System.out.println("done"); 
    } 


// JVM bytecode 
    Offset Instruction  Comments (Method: testMonitor) 
    0  new 42   (java.lang.Boolean) 
    3  dup 
    4  iconst_0 
    5  invokespecial 44 (java.lang.Boolean.<init>) 
    8  astore_1   (java.lang.Boolean x) 
    9  aload_1   (java.lang.Boolean x) 
    10  dup 
    11  astore_2 
    12  monitorenter 
    13  getstatic 15  (java.lang.System.out) 
    16  ldc 47   (inside synchronized) 
    18  invokevirtual 23 (java.io.PrintStream.println) 
    21  getstatic 15  (java.lang.System.out) 
    24  ldc 49   (blah) 
    26  invokevirtual 23 (java.io.PrintStream.println) 
    29  aload_2 
    30  monitorexit 
    31  goto 37 
    34  aload_2 
    35  monitorexit 
    36  athrow 
    37  getstatic 15  (java.lang.System.out) 
    40  ldc 51   (done) 
    42  invokevirtual 23 (java.io.PrintStream.println) 
    45  return 

उत्तर

2

मैं जहां यह JLS में है पता नहीं है, लेकिन यह कहीं न कहीं कहना होगा कि जब एक अपवाद फेंक दिया जाता है, एक ताला जारी किया गया है। आप Unsafe.monitorEnter साथ ऐसा कर सकते/बाहर निकलें

void testMonitor() { 
    Boolean x = new Boolean(false); 
    theUnsafe.monitorEnter(x); 
    try { 
     System.out.println("inside synchronized"); 
     System.out.println("blah"); 
    } catch(Throwable t) { 
     theUnsafe.monitorExit(x); 
     throw t; 
    }; 
    theUnsafe.monitorExit(x); 
    System.out.println("done"); 
} 

मेरा मानना ​​है कि अंत में आप गायब हो सकता है पर एक कैच ब्लॉक तालिका है।

+0

हैलो पीटर, आपका उत्तर इस सवाल का जवाब नहीं देता है: "मुझे उत्सुकता है कि कोड क्यों उत्पन्न होता है" या यहां तक ​​कि "क्या मुझे कुछ याद आया?"। यद्यपि आपकी भागीदारी के लिए धन्यवाद। – chuacw

+0

कोड जेनरेट किया गया है क्योंकि लॉक को रिलीज़ करने के लिए कोड होना है, मेरा उदाहरण देखें। आपने व्याख्या करने के अपने प्रयास को याद किया। ;) –

+0

रेन की व्याख्या बेहतर है। साथ ही, ध्यान दें कि मैंने वैकल्पिक तरीके से नहीं पूछा था। फिर भी धन्यवाद। – chuacw

7

कंपाइलर मॉनिटर स्टेटस जारी होने के लिए यहां एक अदृश्य प्रयास/पकड़ ब्लॉक जोड़ता है (जो वीएम चश्मा में प्रलेखित है, पोस्ट के नीचे देखें)। आप javap -v का उपयोग करके यह सत्यापित करने और अपवाद की मेज पर देख सकते हैं:

void testMonitor(); 
    Code: 
    Stack=3, Locals=3, Args_size=1 
    0: new #15; //class java/lang/Boolean 
    3: dup 
    4: iconst_0 
    5: invokespecial #17; //Method java/lang/Boolean."<init>":(Z)V 
    8: astore_1 
    9: aload_1 
    10: dup 
    11: astore_2 
    12: monitorenter 
    13: getstatic #20; //Field java/lang/System.out:Ljava/io/PrintStream; 
    16: ldc #26; //String inside synchronized 
    18: invokevirtual #28; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 
    21: getstatic #20; //Field java/lang/System.out:Ljava/io/PrintStream; 
    24: ldc #34; //String blah 
    26: invokevirtual #28; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 
    29: aload_2 
    30: monitorexit 
    31: goto 37 
    34: aload_2 
    35: monitorexit 
    36: athrow 
    37: getstatic #20; //Field java/lang/System.out:Ljava/io/PrintStream; 
    40: ldc #36; //String done 
    42: invokevirtual #28; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 
    45: return 
    Exception table: 
    from to target type 
    13 31 34 any 
    34 36 34 any 

संपादित करें: JVM specs से:

आम तौर पर, जावा प्रोग्रामिंग भाषा के लिए एक संकलक सुनिश्चित करता है कि ताला आपरेशन द्वारा कार्यान्वित एक monitorenter निर्देश सिंक्रनाइज़ कथन के शरीर के निष्पादन से पहले एक monitorexit निर्देश द्वारा अनुक्रमित अनलॉक ऑपरेशन से मेल खाता है जब सिंक्रनाइज़ कथन पूर्ण हो जाता है, चाहे पूरा होना सामान्य या अचानक है।

+0

हैलो रेन, धन्यवाद। – chuacw

+0

आपका स्वागत है ;-)। – Neet

संबंधित मुद्दे