यह पद्धति 4 क्यों प्रिंट होती है?


111

मैं सोच रहा था कि क्या होता है जब आप एक StackOverflowError को पकड़ने की कोशिश करते हैं और निम्नलिखित विधि के साथ आते हैं:

class RandomNumberGenerator {

    static int cnt = 0;

    public static void main(String[] args) {
        try {
            main(args);
        } catch (StackOverflowError ignore) {
            System.out.println(cnt++);
        }
    }
}

अब मेरा सवाल:

यह पद्धति '4' को क्यों छापती है?

मुझे लगा शायद System.out.println()कॉल स्टैक पर 3 सेगमेंट की जरूरत थी , लेकिन मुझे नहीं पता कि नंबर 3 कहां से आता है। जब आप स्रोत कोड (और bytecode) को देखते हैं System.out.println(), तो यह सामान्य रूप से 3 की तुलना में कहीं अधिक विधि इनवोकेशन को जन्म देगा (इसलिए कॉल स्टैक पर 3 खंड पर्याप्त नहीं होंगे)। यदि यह अनुकूलन के कारण हॉटस्पॉट वीएम लागू होता है (विधि inlining), मुझे आश्चर्य है कि यदि परिणाम दूसरे वीएम पर अलग होगा।

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

जैसा कि आउटपुट अत्यधिक JVM विशिष्ट लगता है, मुझे
जावा (TM) एसई रनटाइम एनवायरमेंट (बिल्ड 1.6.0_41-b02)
जावा हॉटस्पॉट (TM) 64-बिट सर्वर VM (बिल्ड 20.14-b01, मिश्रित मोड) का उपयोग करके परिणाम 4 मिलता है।


स्पष्टीकरण क्यों मुझे लगता है कि यह सवाल जावा स्टैक को समझने से अलग है :

मेरा प्रश्न इस बारे में नहीं है कि कोई cnt> 0 क्यों है (जाहिर है क्योंकि System.out.println()स्टैक के आकार की आवश्यकता होती है और StackOverflowErrorकुछ और छपने से पहले दूसरे को फेंक देता है ), लेकिन क्यों इसमें 4 का विशेष मूल्य है, क्रमशः 0,3,8,55 या कुछ और पर सिस्टम।


4
मेरे स्थानीय में, मुझे उम्मीद के मुताबिक "0" मिल रहा है।
रेड्डी

2
यह बहुत सारे आर्किटेक्चर सामान के साथ सौदा कर सकता है। तो बेहतर है jdk संस्करण के साथ अपना आउटपुट पोस्ट करें। मेरे लिए आउटपुट jdk 1.7 पर 0 है
लोकेश

3
मैं मिल गया है 5, 6और 38जावा 1.7.0_10 साथ
कॉन

8
जब आप अंतर्निहित स्थापत्य कला को शामिल कर रहे हैं तो @Elist समान आउटपुट नहीं होगा;)
m0skit0

3
@flrnb यह सिर्फ एक शैली है जिसका उपयोग मैं ब्रेसिज़ को लाइन करने के लिए करता हूं। इससे मेरे लिए यह जानना आसान हो जाता है कि स्थितियां और कार्य कहां से शुरू और समाप्त होते हैं। आप चाहें तो इसे बदल सकते हैं, लेकिन मेरी राय में यह इस तरह से अधिक पठनीय है।
syb0rg

जवाबों:


41

मुझे लगता है कि दूसरों ने यह समझाने का अच्छा काम किया है कि क्यों cnt> 0, लेकिन cnt = 4 के बारे में पर्याप्त विवरण नहीं है, और cnt अलग-अलग सेटिंग्स के बीच इतने व्यापक रूप से भिन्न क्यों है। मैं यहां उस शून्य को भरने का प्रयास करूंगा।

चलो

  • X कुल स्टैक आकार है
  • जब हम पहली बार मुख्य प्रवेश करते हैं तो स्टैक स्पेस का उपयोग किया जाता है
  • हर बार जब हम मुख्य में प्रवेश करते हैं तो स्टैक स्पेस में वृद्धि होती है
  • P चलाने के लिए आवश्यक स्टैक स्थान होना चाहिए System.out.println

जब हम पहली बार मुख्य में आते हैं, तो बचा हुआ स्थान एक्सएम होता है। प्रत्येक पुनरावर्ती कॉल R अधिक मेमोरी लेता है। तो 1 पुनरावर्ती कॉल (मूल से 1 अधिक) के लिए, मेमोरी उपयोग M + R है। मान लीजिए कि St सफलOverflowError C सफल पुनरावर्ती कॉल के बाद फेंक दिया जाता है, अर्थात M + C * R <= X और M + C * (R +) 1)> X. पहली StackOverflowError के समय, X - M - C * R मेमोरी बची है।

चलाने में सक्षम होना System.out.prinln , हमें स्टैक पर बचे हुए स्थान की P राशि की आवश्यकता है। यदि ऐसा होता है कि एक्स - एम - सी * आर> = पी, तो 0 मुद्रित किया जाएगा। यदि P को अधिक स्थान की आवश्यकता है, तो हम cnt ++ की कीमत पर R मेमोरी प्राप्त करके, स्टैक से फ्रेम निकालते हैं।

जब printlnआखिरकार चलाने में सक्षम है, तो X - M - (C - cnt) * R> = P. इसलिए यदि P किसी विशेष प्रणाली के लिए बड़ा है, तो cnt बड़ा होगा।

आइए इसे कुछ उदाहरणों के साथ देखें।

उदाहरण 1: मान लीजिए

  • एक्स = 100
  • एम = 1
  • आर = 2
  • पी = 1

फिर सी = मंजिल ((एक्सएम) / आर) = 49, और सेंट = छत ((पी - (एक्स - एम - सी * आर)) / आर) = 0।

उदाहरण 2: मान लीजिए कि

  • एक्स = 100
  • एम = 1
  • आर = ५
  • पी = 12

फिर C = 19, और cnt = 2।

उदाहरण 3: मान लीजिए कि

  • एक्स = 101
  • एम = 1
  • आर = ५
  • पी = 12

फिर C = 20, और cnt = 3।

उदाहरण 4: मान लीजिए कि

  • एक्स = 101
  • म = २
  • आर = ५
  • पी = 12

फिर C = 19, और cnt = 2।

इस प्रकार, हम देखते हैं कि सिस्टम (M, R, और P) और स्टैक आकार (X) दोनों ही cnt को प्रभावित करते हैं।

एक साइड नोट के रूप में, इससे कोई फर्क नहीं पड़ता कि कितना स्थान catchशुरू करने की आवश्यकता है। जब तक के लिए पर्याप्त जगह नहीं है catch, तब तक cnt नहीं बढ़ेगा, इसलिए कोई बाहरी प्रभाव नहीं हैं।

संपादित करें

मैंने जो कहा उसके बारे में वापस लेता हूं catch। यह एक भूमिका निभाता है। मान लीजिए कि इसे शुरू करने के लिए टी राशि की जगह चाहिए। जब बायाँ स्थान T से अधिक होता है, और cnt वृद्धि करना शुरू कर देता हैprintln जब बायाँ स्थान T + P से बड़ा होता है, तो यह गणना के लिए एक अतिरिक्त कदम जोड़ता है और पहले से मैला विश्लेषण को आगे बढ़ाता है।

संपादित करें

मुझे अंततः अपने सिद्धांत का समर्थन करने के लिए कुछ प्रयोग चलाने का समय मिला। दुर्भाग्य से, सिद्धांत प्रयोगों के साथ मेल नहीं खाता है। वास्तव में जो होता है वह बहुत अलग होता है।

प्रयोग सेटअप: डिफ़ॉल्ट जावा और डिफ़ॉल्ट- jdk के साथ Ubuntu 12.04 सर्वर। Xss 70,000 से 1 बाइट की वृद्धि पर 460,000 से शुरू होता है।

परिणाम यहां उपलब्ध हैं: https://www.google.com/fusiontables/DataSource?docid=1xkJhd4s8biLghe6gZbcfUs3vT5MpS_OnscjwWDMM मैंने एक और संस्करण बनाया है जहां हर दोहराया डेटा बिंदु हटा दिया जाता है। दूसरे शब्दों में, केवल उन बिंदुओं को दिखाया गया है जो पहले से भिन्न हैं। इससे विसंगतियों को देखना आसान हो जाता है। https://www.google.com/fusiontables/DataSource?docid=1XG_SRzrrNasepwZoNHqEAKuZlHiAm9vbEdwfsUA


अच्छे सारांश के लिए धन्यवाद, मुझे लगता है कि यह सब इस सवाल से उबलता है: एम, आर और पी (चूंकि एक्स को वीएम-विकल्प-एक्सएसएस द्वारा सेट किया जा सकता है) क्या प्रभाव डालता है?
15

@flrnb M, R, और P सिस्टम विशिष्ट हैं। आप आसानी से उन को नहीं बदल सकते। मैं उनसे कुछ रिलीज के बीच भी अंतर करने की उम्मीद करता हूं।
जॉन त्सेंग जूल

फिर, मुझे Xss (उर्फ X) को बदलकर अलग-अलग परिणाम क्यों मिले? X को 100 से 10000 में बदलना, यह देखते हुए कि M, R और P एक ही है, को आपके सूत्र के अनुसार cnt को प्रभावित नहीं करना चाहिए, या क्या मैं गलत हूं?
flrnb

@flrnb X अकेले इन चरों की असतत प्रकृति के कारण cnt नहीं बदलता है। उदाहरण 2 और 3 केवल X पर भिन्न हैं, लेकिन cnt अलग है।
जॉन त्सेंग

1
@ जॉनसन मैं भी आपके जवाब को अब तक का सबसे समझदार और पूर्ण मानता हूं - वैसे भी, मुझे वास्तव में इस बात में दिलचस्पी होगी कि वास्तव में स्टैक को फेंके गए पल की तरह दिखताStackOverflowError है और यह आउटपुट को कैसे प्रभावित करता है। यदि इसमें केवल ढेर के ढेर का संदर्भ होता है (जैसा कि जे ने सुझाव दिया है), तो आउटपुट किसी दिए गए सिस्टम के लिए काफी अनुमानित होना चाहिए।
21

20

यह खराब पुनरावर्ती कॉल का शिकार है। जैसा कि आप सोच रहे हैं कि क्यूटी का मूल्य अलग-अलग क्यों है , यह इसलिए है क्योंकि स्टैक का आकार प्लेटफॉर्म पर निर्भर करता है। विंडोज़ पर जावा एसई 6 में 32-बिट वीएम में 320k का डिफ़ॉल्ट स्टैक आकार और 64-बिट वीएम में 1024k है। आप यहाँ और पढ़ सकते हैं ।

आप विभिन्न स्टैक आकारों का उपयोग करके चला सकते हैं और आपको अलग-अलग मान दिखाई देंगे स्टैक ओवरफ्लो से पहले आपको cnt के देंगे-

java -Xss1024k randomNumberGenerator

आपको कई बार मुद्रित होने वाले cnt का मान दिखाई नहीं देता, भले ही मान कभी-कभी 1 से अधिक हो, क्योंकि आपका प्रिंट स्टेटमेंट भी त्रुटि फेंक रहा है, जिसे आप ग्रहण या अन्य IDE के माध्यम से सुनिश्चित करने के लिए डिबग कर सकते हैं।

यदि आप चाहें तो प्रति कथन निष्पादन के लिए कोड को निम्नलिखित में बदल सकते हैं-

static int cnt = 0;

public static void main(String[] args) {                  

    try {     

        main(args);   

    } catch (Throwable ignore) {

        cnt++;

        try { 

            System.out.println(cnt);

        } catch (Throwable t) {   

        }        
    }        
}

अपडेट करें:

जैसा कि यह बहुत अधिक ध्यान दे रहा है, चलो चीजों को स्पष्ट करने के लिए एक और उदाहरण है-

static int cnt = 0;

public static void overflow(){

    try {     

      overflow();     

    } catch (Throwable t) {

      cnt++;                      

    }

}

public static void main(String[] args) {

    overflow();
    System.out.println(cnt);

}

हम एक और तरीका नाम बनाया अतिप्रवाह एक बुरा प्रत्यावर्तन करने के लिए और हटाया println कैच ब्लॉक से बयान तो यह त्रुटियों का एक और सेट फेंक मुद्रित करने के लिए प्रयास करने के दौरान शुरू नहीं करता है। यह उम्मीद के मुताबिक काम करता है। आप System.out.println (cnt) डालने की कोशिश कर सकते हैं ; cnt ++ के बाद का स्टेटमेंट और संकलन। फिर कई बार चला। आपके प्लेटफॉर्म के आधार पर, आपको cnt के विभिन्न मूल्य मिल सकते हैं ।

यही कारण है कि आम तौर पर हम त्रुटियों को नहीं पकड़ते क्योंकि कोड में रहस्य कल्पना नहीं है।


13

व्यवहार स्टैक आकार (जो मैन्युअल रूप से सेट किया जा सकता है) पर निर्भर है Xss। स्टैक आकार आर्किटेक्चर विशिष्ट है। JDK 7 स्रोत कोड से :

// विंडोज पर डिफ़ॉल्ट स्टैक का आकार निष्पादन योग्य द्वारा निर्धारित किया जाता है (java.exe
// का डिफ़ॉल्ट मान 320K / 1MB [32bit / 64bit]) है। विंडोज संस्करण के आधार पर,
गैर-शून्य पर // थ्रेडस्टैक को बदलने से मेमोरी उपयोग पर महत्वपूर्ण प्रभाव पड़ सकता है।
// os_windows.cpp में टिप्पणियां देखें।

इसलिए जब StackOverflowErrorफेंक दिया जाता है, तो त्रुटि पकड़ ब्लॉक में पकड़ी जाती है। यहां println()एक और स्टैक कॉल है जो अपवाद को फिर से फेंकता है। यह दोहराया जाता है।

कितनी बार दोहराता है? - वैसे यह इस बात पर निर्भर करता है कि कब JVM को लगता है कि यह स्टैकओवरफ्लो नहीं है। और यह प्रत्येक फ़ंक्शन कॉल के स्टैक आकार (खोजने में मुश्किल) और पर निर्भर करता है Xss। जैसा कि प्रत्येक फ़ंक्शन कॉल के डिफ़ॉल्ट कुल आकार और आकार के ऊपर उल्लिखित है (मेमोरी पेज आकार आदि पर निर्भर करता है) प्लेटफ़ॉर्म विशिष्ट है। इसलिए अलग व्यवहार।

कॉलिंग javaकॉल के साथ -Xss 4Mमुझे देता है 41। इसलिए सहसंबंध।


4
मुझे नहीं लगता कि स्टैक का आकार परिणाम को प्रभावित क्यों करे, क्योंकि यह पहले से ही अधिक है जब हम cnt के मूल्य को प्रिंट करने का प्रयास करते हैं। इस प्रकार, केवल अंतर "प्रत्येक फ़ंक्शन कॉल के स्टैक आकार" से आ सकता है। और मुझे समझ में नहीं आता है कि यह एक ही JVM संस्करण चलाने वाली 2 मशीनों के बीच भिन्न क्यों होना चाहिए।
flrnb

सटीक व्यवहार केवल जेवीएम स्रोत से प्राप्त किया जा सकता है। लेकिन कारण यह हो सकता है। यहां तक ​​कि याद रखें कि catchएक ब्लॉक है और जो स्टैक पर मेमोरी रखता है। प्रत्येक विधि कॉल कितना मेमोरी लेती है यह ज्ञात नहीं किया जा सकता है। जब स्टैक साफ़ हो जाता है, तो आप एक और ब्लॉक जोड़ रहे हैं catch। यह व्यवहार हो सकता है। यह केवल अटकलें हैं।
जतिन

और स्टैक का आकार दो अलग-अलग मशीनों में भिन्न हो सकता है। ढेर का आकार बहुत सारे ओएस-आधारित कारकों पर निर्भर करता है जैसे कि मेमोरी पेज-साइज़ आदि
जतिन

6

मुझे लगता है कि प्रदर्शित संख्या उस समय की संख्या है जब System.out.printlnकॉल Stackoverflowअपवाद को फेंकता है।

यह संभवतः इसके कार्यान्वयन printlnऔर उस पर किए गए स्टैकिंग कॉल की संख्या पर निर्भर करता है।

चित्र के रूप में:

main()कॉल ट्रिगर Stackoverflowकॉल मैं अपवाद। मुख्य के i-1 कॉल अपवाद को पकड़ते हैं और कॉल printlnजो एक दूसरे को ट्रिगर करते हैं Stackoverflowcntवेतन वृद्धि 1. मुख्य-पकड़ के i-2 कॉल अब अपवाद और कॉल println। में printlnएक विधि एक 3 अपवाद ट्रिगर कहा जाता है। cnt2. वृद्धि प्राप्त करें। यह तब तक जारी रहती है जब तक कि printlnइसकी सभी आवश्यक कॉल नहीं हो सकती और अंत में इसका मूल्य प्रदर्शित किया जाए cnt

यह तब के वास्तविक कार्यान्वयन पर निर्भर है println

JDK7 के लिए या तो यह साइकलिंग कॉल का पता लगाता है और अपवाद को पहले फेंक देता है या तो यह कुछ स्टैक रिसोर्स रखता है और रेमेडिएशन लॉजिक के लिए कुछ कमरे में पहुंचने से पहले अपवाद को फेंक देता है या तो printlnकार्यान्वयन कॉल नहीं करता है या तो ++ ऑपरेशन किया जाता है। इस printlnप्रकार कॉल अपवाद द्वारा पास है।


इसका मतलब है कि "मुझे लगा कि शायद यह इसलिए था क्योंकि System.out.println को कॉल स्टैक पर 3 सेगमेंट की आवश्यकता होती है" - लेकिन मुझे आश्चर्य हुआ कि यह वास्तव में यह संख्या क्यों है और अब मैं और भी हैरान हूं कि संख्या इतने बड़े पैमाने पर भिन्न क्यों है (वर्चुअल) मशीनें
flrnb

मैं इसके लिए आंशिक रूप से सहमत हूं लेकिन मैं इस कथन पर असहमत हूं कि 'प्रिंटलाइन के वास्तविक कार्यान्वयन पर निर्भर है।' यह कार्यान्वयन के बजाय प्रत्येक jvm में स्टैक आकार के साथ किया गया है।
जतिन

6
  1. mainजब तक यह पुनरावृत्ति की गहराई पर ढेर को उखाड़ नहीं लेती, तब तक खुद पर पुनरावृत्ति होती है R
  2. रिकर्सन डेप्थ पर कैच ब्लॉक R-1चलाया जाता है।
  3. रिकर्सन डेप्थ पर कैच ब्लॉक R-1मूल्यांकन करता है cnt++
  4. स्टैक पर पुराने मूल्य रखने, गहराई R-1कॉल पर पकड़ ब्लॉक । आंतरिक रूप से अन्य विधियों को कॉल करेगा और स्थानीय चर और चीजों का उपयोग करेगा। इन सभी प्रक्रियाओं के लिए स्टैक स्पेस की आवश्यकता होती है।printlncntprintln
  5. क्योंकि स्टैक पहले से ही सीमा पर चराई कर रहा था, और कॉलिंग / निष्पादित करने के printlnलिए स्टैक स्पेस की आवश्यकता होती है, गहराई के R-1बजाय एक नया स्टैक ओवरफ्लो शुरू होता है R
  6. चरण 2-5 फिर से होते हैं, लेकिन पुनरावृत्ति गहराई पर R-2
  7. चरण 2-5 फिर से होते हैं, लेकिन पुनरावृत्ति गहराई पर R-3
  8. चरण 2-5 फिर से होते हैं, लेकिन पुनरावृत्ति गहराई पर R-4
  9. चरण 2-4 फिर से होते हैं, लेकिन पुनरावृत्ति गहराई पर R-5
  10. ऐसा होता है कि printlnपूरा करने के लिए पर्याप्त स्टैक स्पेस है (ध्यान दें कि यह एक कार्यान्वयन विवरण है, यह भिन्न हो सकता है)।
  11. cntगहराई में वृद्धि के बाद किया गया था R-1, R-2, R-3, R-4, और अंत में पर R-5। पांचवें पोस्ट-इन्क्रीमेंट ने चार लौटाए, जो छपे थे।
  12. mainगहराई से सफलतापूर्वक पूरा होने के साथ R-5, पूरे स्टैक को बिना अधिक पकड़ वाले ब्लॉक के बिना चला जाता है और प्रोग्राम पूरा हो जाता है।

1

थोड़ी देर के लिए चारों ओर खुदाई करने के बाद, मैं यह नहीं कह सकता कि मुझे जवाब मिल गया है, लेकिन मुझे लगता है कि यह अब काफी करीब है।

सबसे पहले, हमें यह जानना StackOverflowErrorहोगा कि कब फेंका जाएगा। वास्तव में, एक जावा थ्रेड स्टोर फ्रेम के लिए स्टैक, जिसमें एक विधि को फिर से शुरू करने और फिर से शुरू करने के लिए आवश्यक सभी डेटा होते हैं। जावा 6 के लिए जावा लैंग्वेज स्पेसिफिकेशन्स के अनुसार , किसी विधि को लागू करते समय,

यदि ऐसी सक्रियण फ़्रेम बनाने के लिए पर्याप्त मेमोरी उपलब्ध नहीं है, तो StackOverflowError को फेंक दिया जाता है।

दूसरा, हमें यह स्पष्ट करना चाहिए कि " ऐसा सक्रियण फ्रेम बनाने के लिए पर्याप्त मेमोरी उपलब्ध नहीं है "। जावा 6 के लिए जावा वर्चुअल मशीन विनिर्देशों के अनुसार ,

फ्रेम ढेर आवंटित किया जा सकता है।

इसलिए, जब एक फ्रेम बनाया जाता है, तो स्टैक फ्रेम बनाने के लिए पर्याप्त ढेर जगह होनी चाहिए और नए संदर्भ को संग्रहीत करने के लिए पर्याप्त स्टैक स्पेस होना चाहिए जो कि फ्रेम ढेर आवंटित होने पर नए स्टैक फ्रेम को इंगित करता है।

अब चलिए सवाल पर लौटते हैं। ऊपर से, हम यह जान सकते हैं कि जब कोई विधि निष्पादित होती है, तो उसे स्टैक स्पेस की समान राशि खर्च करनी पड़ सकती है। और इनवोकिंग System.out.println(हो सकता है) के लिए 5 स्तर की विधि मंगलाचरण की जरूरत है, इसलिए 5 फ्रेम बनाने की आवश्यकता है। फिर कबStackOverflowError बाहर फेंक दिया जाता है, तो 5 फ्रेम के संदर्भों को संग्रहीत करने के लिए पर्याप्त स्टैक स्थान प्राप्त करने के लिए 5 बार वापस जाना पड़ता है। इसलिए 4 का प्रिंट आउट है। 5 क्यों नहीं? क्योंकि आप उपयोग करते हैं cnt++। इसे बदलें ++cnt, और फिर आपको 5 मिलेंगे।

और आप देखेंगे कि जब स्टैक का आकार उच्च स्तर पर जाता है, तो आपको कभी-कभी 50 मिलेंगे। ऐसा इसलिए है क्योंकि उपलब्ध ढेर स्थान की मात्रा को तब ध्यान में रखा जाना चाहिए। जब स्टैक का आकार बहुत बड़ा होता है, तो ढेर से पहले ढेर का स्थान निकल जाएगा। और (शायद) स्टैक फ्रेम का वास्तविक आकार System.out.printlnलगभग 51 गुना है main, इसलिए यह 51 बार वापस जाता है और 50 प्रिंट करता है।


मेरा पहला विचार यह भी था कि मैथ्यू इनवोकेशंस के स्तर को गिना जाए (और आप सही कह रहे हैं, मैंने इस तथ्य पर ध्यान नहीं दिया कि मैं इंक्रीमेंट सेंट करता हूं), लेकिन अगर समाधान इतना आसान था, तो परिणाम प्लेटफॉर्मों में बहुत भिन्न होंगे। और वीएम कार्यान्वयन?
flrnb

@flrnb ऐसा इसलिए है क्योंकि विभिन्न प्लेटफ़ॉर्म स्टैक फ्रेम के आकार को प्रभावित कर सकते हैं और jre के अलग-अलग संस्करण कार्यान्वयन System.out.printया विधि निष्पादन की रणनीति को प्रभावित करेंगे । जैसा कि ऊपर वर्णित है, वीएम कार्यान्वयन भी प्रभावित करता है जहां स्टैक फ्रेम वास्तविक संग्रहीत होगा।
जय

0

यह वास्तव में इस सवाल का जवाब नहीं है, लेकिन मैं सिर्फ मूल प्रश्न के साथ कुछ जोड़ना चाहता था जो मुझे आया था और मैंने इस समस्या को कैसे समझा:

मूल समस्या में अपवाद को पकड़ा जाता है जहाँ यह संभव था:

उदाहरण के लिए jdk 1.7 के साथ यह घटना के पहले स्थान पर पकड़ा गया है।

लेकिन jdk के पहले के संस्करणों में ऐसा लग रहा है कि अपवाद घटित होने के पहले स्थान पर नहीं पकड़ा जा रहा है इसलिए 4, 50 आदि।

अब यदि आप निम्न के रूप में कोशिश पकड़ ब्लॉक को हटा दें

public static void main( String[] args ){
    System.out.println(cnt++);
    main(args);
}

तब आपको सभी मान दिखाई देंगे cnt चींटी के अपवाद के (jdk 1.7 पर)।

मैंने आउटपुट को देखने के लिए netbeans का उपयोग किया, क्योंकि cmd सभी आउटपुट और अपवाद नहीं दिखाएगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.