क्या आखिरकार ब्लॉक हमेशा चलता है?


112

क्या कोई ऐसी स्थिति है जहाँ अंत में जावा में नहीं चल सकता है? धन्यवाद।


13
क्या यह एक ऐसा सवाल है जो आपसे पूछा जा सकता है जब आप एक निश्चित नामी कंपनी के साथ नौकरी पाने की कोशिश कर रहे हैं?
टॉम हॉल्टिन -

@ टॉमहॉटिन-टैक्लाइन केयर इसे नाम दें? (भगवान, मुझे याद आया कि यह पद कितना पुराना था!)
हेले

6
@ मैं खेल को दूर नहीं देना चाहता, लेकिन आप इसे गूगल कर सकते हैं।
टॉम हैटिन -

संक्षिप्त उत्तर: हां, सामान्य परिस्थितियों में।
शार्क

जवाबों:


139

से सूर्य ट्यूटोरियल

नोट: यदि JVM कोशिश या कैच कोड निष्पादित करते समय बाहर निकलता है, तो अंत में ब्लॉक निष्पादित नहीं हो सकता है। इसी तरह, यदि कोशिश या कैच कोड को निष्पादित करने वाला थ्रेड बाधित होता है या मारा जाता है, तो अंत में भले ही एप्लिकेशन पूरे जारी रहे, लेकिन निष्पादित नहीं हो सकता है।

मैं किसी भी अन्य तरीके से नहीं जानता कि आखिरकार ब्लॉक निष्पादित नहीं होगा ...


6
@dhiller - मुझे पूरा यकीन है कि "पावर डाउन" में शामिल है अगर "JVM बाहर निकलता है ...":
जेसन कोको

2
@ जैसन कोको: समाप्त करना (बिजली की हानि के रूप में) बाहर निकलने के समान नहीं है; उत्तरार्द्ध एक कम या ज्यादा संगठित प्रक्रिया है जिसका समापन पूर्व में हुआ है। ; पी
user359996

2
AFAIK, यदि एक धागा बाधित है, तो यह तुरंत रुका नहीं है। यह रुकावट का पता लगाने और अपने कार्य को रोकने के लिए थ्रेड में कोड तक है, इसलिए अंत में कोड चलना चाहिए।
बार्ट वैन ह्युकेलम

2
मुझे लगता है कि अगर अंत में ब्लॉक में एक अपवाद को फेंक दिया जाता है, तो बाकी ब्लॉक को निष्पादित नहीं किया जाता है।
एड्रियन कोस्टर

अच्छा है कि बेकार है!
ईरान

63

System.exit वर्चुअल मशीन को बंद कर देता है।

वर्तमान में चल रहे जावा वर्चुअल मशीन को समाप्त करता है। तर्क एक स्थिति कोड के रूप में कार्य करता है; कन्वेंशन द्वारा, एक नॉनज़रो स्टेटस कोड असामान्य समाप्ति को इंगित करता है।

यह विधि exitविधि को कक्षा में बुलाती है Runtime। यह विधि सामान्य रूप से कभी नहीं लौटती है।

    try {
        System.out.println("hello");
        System.exit(0);
    }
    finally {
        System.out.println("bye");
    } // try-finally

"अलविदा" उपरोक्त कोड में प्रिंट नहीं करता है।


इसके अलावा एक अपवाद को जावा वर्चुअल मशीन को बंद कर देना चाहिए।
kaissun

3
यदि System.exit (0) निष्पादित करते समय एक अपवाद होता है, तो अंत में हालांकि निष्पादित करेगा।
आधा

50

बस दूसरों ने जो कुछ भी कहा है, उस पर विस्तार करने के लिए, जेवीएम से बाहर निकलने जैसा कुछ भी नहीं होता है जो अंततः ब्लॉक को उकसाएगा। तो निम्न विधि:

public static int Stupid() {
  try {
    return 0;
  }
  finally {
    return 1;
  }
}

दोनों संकलित करेंगे और 1 वापस करेंगे।


2
यह वास्तव में मुझे कुछ हफ़्ते पहले कुछ घंटों के लिए अच्छा लगा।
निकफ

3
अंत में ब्लॉक से मान लौटाना एक बुरा विचार है। या तो केवल कोशिश ब्लॉक से लौटें, या कोशिश / अंत में ब्लॉक के बाहर से लौटें। अधिकांश IDE इसे चेतावनी के साथ चिह्नित करेंगे।
शाम

1
@nickf मैं इकट्ठा करता हूं कि आप अब भ्रमित नहीं हैं। क्या आप 1 के मैकेनिक के बारे में विस्तार से बता सकते हैं कि क्यों 1 लौटाया गया है और 0. मैं केवल यह अनुमान लगा सकता हूं कि मेमोरी (या यह एक रजिस्टर है) जो फ़ंक्शन के रिटर्न मान को संग्रहीत करता है जो शुरू में 0 रखता है, इसे ओवरराइट किया जाता है क्योंकि अंत में ब्लॉक निष्पादित होता है। ।
यानि

2
यह उत्सुक है, सी # में यह अंततः ब्लॉक से वापस जाने की अनुमति नहीं है।
JMCF125

3
@RanBiron बेशक। वह वास्तव में अंत में ब्लॉक के अंदर लौटने की सिफारिश नहीं कर रहा था, वह केवल यह प्रदर्शित करने की कोशिश कर रहा था कि यहां तक ​​कि रिटर्न स्टेटमेंट को निष्पादित करने के लिए उक्त ब्लॉक में कोड का कारण होगा।
एक्वेरेल

15

System.exit से संबंधित, कुछ प्रकार की भयावह विफलताएं भी हैं, जहां अंततः ब्लॉक निष्पादित नहीं हो सकता है। यदि JVM पूरी तरह से मेमोरी से बाहर निकलता है, तो यह बिना कैच के आउट हो सकता है या अंत में हो सकता है।

विशेष रूप से, मुझे एक परियोजना याद है, जहां हमने मूर्खता से उपयोग करने की कोशिश की थी

catch (OutOfMemoryError oome) {
    // do stuff
}

यह काम नहीं किया क्योंकि जेवीएम में कैच ब्लॉक को निष्पादित करने के लिए कोई मेमोरी नहीं थी।


जब OutOfMemoryError को फेंक दिया जाता है, तो आमतौर पर बहुत सारी मेमोरी छोड़ दी जाती है (जीसी थ्रशिंग को रोकने के लिए)। हालांकि, यदि आप इसे बार-बार पकड़ते हैं तो आप स्पष्ट रूप से जीसी थ्रशिंग पर वापस पहुंचेंगे।
टॉम हॉल्टिन -

मैंने सोचा कि किसी को भी अनियंत्रित अपवाद नहीं पकड़ना चाहिए!
सेर्गी शेवचेक

1
मैंने अपने पक्ष में कोशिश की, jdk7 का उपयोग करते हुए, लेकिन इसने आउटऑफमेरी एरर को पकड़ लिया!
जसकी

10
try { for (;;); } finally { System.err.println("?"); }

उस स्थिति में अंत में निष्पादित नहीं होगा (जब तक कि पदावनत Thread.stopको बुलाया नहीं जाता है, या एक उपकरण इंटरफ़ेस के माध्यम से एक समकक्ष, कहते हैं)।


यह पृष्ठ दावा करता है कि थ्रेडडॉट त्रुटि को फेंक दिया गया है, और थ्रेड.स्टॉप () कहा जाने पर स्टैक सामान्य रूप से समाप्त हो जाता है। क्या कोई पकड़ है जो मुझे याद आ रही है? download.oracle.com/docs/cd/E17476_01/javase/1.5.0/docs/guide/…
spurserh

मुझे नहीं लगता कि कोई कैच है। शायद वहाँ आप एक पकड़ने की कल्पना कर रहे हैं जो वहाँ नहीं है। यदि हम स्पष्ट रूप से डालते हैं throw, तो finallyब्लॉक अपेक्षित रूप से निष्पादित करेगा। try { throw new ThreadDeath(); } finally { System.err.println("?"); }
टॉम हॉल्टिन -

9

इस सूत्र में सूर्य ट्यूटोरियल को गलत तरीके से यहां उद्धृत किया गया है।

नोट: यदि JVM कोशिश या कैच कोड निष्पादित करते समय बाहर निकलता है, तो अंत में ब्लॉक निष्पादित नहीं करेगा । इसी तरह, यदि कोशिश या कैच कोड को निष्पादित करने वाला थ्रेड बाधित होता है या मारा जाता है, तो अंत में ब्लॉक हो जाएगा निष्पादित नहीं , भले ही एप्लिकेशन पूरी तरह से जारी रहे।

यदि आप अंत में ब्लॉक के लिए सूर्य ट्यूटोरियल को बारीकी से देखते हैं, तो यह नहीं कहता है "निष्पादित नहीं करेगा" लेकिन "निष्पादित नहीं कर सकता" यहां सही वर्णन है

नोट: यदि JVM कोशिश या कैच कोड निष्पादित करते समय बाहर निकलता है, तो अंत में ब्लॉक निष्पादित नहीं हो सकता है । इसी तरह, यदि कोशिश या कैच कोड को निष्पादित करने वाला थ्रेड बाधित होता है या मारा जाता है, तो अंत में भले ही एप्लिकेशन पूरे जारी रहे, लेकिन निष्पादित नहीं हो सकता है

इस व्यवहार का स्पष्ट कारण है, system.exit पर कॉल करना () रनटाइम सिस्टम थ्रेड में संसाधित होता है जो jvm को बंद करने में समय लग सकता है, इस बीच थ्रेड अनुसूचक अंत में निष्पादित करने के लिए कह सकता है। तो अंत में हमेशा निष्पादित करने के लिए डिज़ाइन किया गया है, लेकिन अगर आप jvm को बंद कर रहे हैं, तो ऐसा हो सकता है कि jvm पहले बंद हो जाए।


6

इसके अलावा अगर कोई गतिरोध / लाइवलॉक अंदर होता है try ब्लॉक के ।

यहाँ वह कोड है जो इसे प्रदर्शित करता है:

public class DeadLocker {
    private static class SampleRunnable implements Runnable {
        private String threadId;
        private Object lock1;
        private Object lock2;

        public SampleRunnable(String threadId, Object lock1, Object lock2) {
            super();
            this.threadId = threadId;
            this.lock1 = lock1;
            this.lock2 = lock2;
        }

        @Override
        public void run() {
            try {
                synchronized (lock1) {
                    System.out.println(threadId + " inside lock1");
                    Thread.sleep(1000);
                    synchronized (lock2) {
                        System.out.println(threadId + " inside lock2");
                    }
                }
            } catch (Exception e) {
            } finally {
                System.out.println("finally");
            }
        }

    }

    public static void main(String[] args) throws Exception {
        Object ob1 = new Object();
        Object ob2 = new Object();
        Thread t1 = new Thread(new SampleRunnable("t1", ob1, ob2));
        Thread t2 = new Thread(new SampleRunnable("t2", ob2, ob1));
        t1.start();
        t2.start();
    }
}

यह कोड निम्नलिखित आउटपुट का उत्पादन करता है:

t1 inside lock1
t2 inside lock1

और "अंत में" कभी भी मुद्रित नहीं होता


3
तकनीकी रूप से, कोशिश करने वाला ब्लॉक कभी बाहर नहीं निकलता है, इसलिए अंत में ब्लॉक को निष्पादित करने का मौका कभी नहीं मिलना चाहिए। अनंत लूप के लिए भी यही कहा जा सकता है।
जेफ मर्काडो

6

यदि कोशिश या कैच कोड निष्पादित करते समय JVM बाहर निकलता है, तो अंत में ब्लॉक निष्पादित नहीं हो सकता है। ( स्रोत )

सामान्य शटडाउन - यह तब होता है जब अंतिम गैर-डेमन थ्रेड बाहर निकलता है या जब रंटाइम.एक्सिट () ( स्रोत )

जब कोई थ्रेड बाहर निकलता है, तो JVM रनिंग थ्रेड्स की एक इन्वेंट्री करता है, और यदि केवल थ्रेड्स जो बचे हुए हैं, डेमन थ्रेड्स हैं, यह एक क्रमिक शटडाउन आरंभ करता है। जब JVM रुकता है, तो किसी भी शेष डेमन थ्रेड्स को छोड़ दिया जाता है अंत में ब्लॉक निष्पादित नहीं किए जाते हैं, स्टैक जेवीएम को केवल बाहर नहीं निकालते हैं। डेमन थ्रेड्स का इस्तेमाल शायद ही कभी किया जाना चाहिए, कुछ प्रसंस्करण गतिविधियों को बिना किसी सफाई के किसी भी समय सुरक्षित रूप से छोड़ दिया जा सकता है। विशेष रूप से, उन कार्यों के लिए डेमन थ्रेड्स का उपयोग करना खतरनाक है जो किसी भी प्रकार का I / O प्रदर्शन कर सकते हैं। डेमॉन थ्रेड्स को "हाउसकीपिंग" कार्यों के लिए सबसे अच्छा सहेजा जाता है, जैसे कि बैकग्राउंड थ्रेड जो समय-समय पर एक इन-मेमोरी कैश से समाप्त प्रविष्टियों को हटा देता है। ( स्रोत )

अंतिम गैर-डेमॉन धागा उदाहरण से बाहर निकलता है:

public class TestDaemon {
    private static Runnable runnable = new Runnable() {
        @Override
        public void run() {
            try {
                while (true) {
                    System.out.println("Is alive");
                    Thread.sleep(10);
                    // throw new RuntimeException();
                }
            } catch (Throwable t) {
                t.printStackTrace();
            } finally {
                System.out.println("This will never be executed.");
            }
        }
    };

    public static void main(String[] args) throws InterruptedException {
        Thread daemon = new Thread(runnable);
        daemon.setDaemon(true);
        daemon.start();
        Thread.sleep(100);
        // daemon.stop();
        System.out.println("Last non-daemon thread exits.");
    }
}

आउटपुट:

Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Last non-daemon thread exits.
Is alive
Is alive
Is alive
Is alive
Is alive

1

निम्नलिखित मामलों में, अंत में ब्लॉक निष्पादित नहीं किया जाएगा: -

  • जब ब्लॉक System.exit(0)से मंगवाया जाता है try
  • जब JVM स्मृति से बाहर चलाता है
  • जब आपके जावा प्रोसेस को टास्क मग या कंसोल से जबरदस्ती मारा जाता है
  • आपके tryब्लॉक में गतिरोध की स्थिति
  • जब आपकी मशीन बिजली की विफलता के कारण बंद हो जाती है

अन्य फ्रिंज मामले भी हो सकते हैं, जहां अंत में ब्लॉक निष्पादित नहीं किया जाएगा।


1

अंत में कोड निष्पादन को रोकने के दो तरीके हैं:
1. System.exit () का उपयोग करें;
2. यदि किसी तरह निष्पादन नियंत्रण ब्लॉक की कोशिश करने के लिए नहीं पहुंचता है।
देख:

public class Main
{
  public static void main (String[]args)
  {
    if(true){
        System.out.println("will exceute");
    }else{
        try{
            System.out.println("result = "+5/0);
        }catch(ArithmeticException e){
          System.out.println("will not exceute");
        }finally{
          System.out.println("will not exceute");  
        }
    }
  }
}

0

मैं आख़िरकार ब्लॉक के एक बहुत ही विशिष्ट मामले में आया हूँ जो विशेष रूप से प्ले फ्रेमवर्क से संबंधित नहीं है।

मुझे यह जानकर आश्चर्य हुआ कि इस कंट्रोलर एक्शन कोड में अंततः ब्लॉक केवल एक अपवाद के बाद मिला, लेकिन कभी भी नहीं जब कॉल वास्तव में सफल हुई।

try {
    InputStream is = getInputStreamMethod();
    renderBinary(is, "out.zip");
catch (Exception e) {
    e.printStackTrace();
} finally {
    cleanUp();
}

शायद थ्रेड को समाप्त कर दिया जाता है या जब रेंडरबिनरी () कहा जाता है। मुझे संदेह होगा कि अन्य रेंडर () कॉल के लिए भी यही बात होती है, लेकिन मैंने इसे सत्यापित नहीं किया।

मैंने कोशिश की / पकड़ने के बाद रेंडरबिनरी () को स्थानांतरित करके समस्या को हल किया। आगे की जांच में पता चला कि प्ले एक @ एनाउंसमेंट एनोटेशन प्रदान करता है जिससे एक कंट्रोलर एक्शन निष्पादित होने के बाद निष्पादित होता है। यहाँ पर चेतावनी यह है कि नियंत्रक में किसी भी कार्रवाई के निष्पादन के बाद इसे कॉल किया जाएगा, इसलिए यह हमेशा एक अच्छा विकल्प नहीं हो सकता है।


-1
//If ArithmeticException Occur Inner finally would not be executed
class Temp
{
    public static void main(String[] s)
    {
        try
        {
        int x = 10/s.length;
        System.out.println(x);
        try
            {
                int z[] = new int[s.length];
                z[10] = 1000;
            }catch(ArrayIndexOutOfBoundsException e)
            {
                System.out.println(e);
            }
         finally
        {
            System.out.println("Inner finally");
        }
        }
        catch(ArithmeticException e)
        {
            System.out.println(e);
        }
    finally 
    {
        System.out.println("Outer Finally"); 
    }

System.out.println("Remaining Code");   
}
}

इंडेंटेशन में सुधार करें और कुछ विवरण जोड़ें।
ROMANIA_engineer

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