हमें जावा में System.exit कब कॉल करना चाहिए


193

जावा में, System.exit(0)निम्नलिखित कोड के साथ या उसके बिना क्या अंतर है ?

public class TestExit
{      
    public static void main(String[] args)
    { 
        System.out.println("hello world");

        System.exit(0);  // is it necessary? And when it must be called? 
    }      
}

दस्तावेज़ कहते हैं: "इस विधि सामान्य रूप से देता है कभी नहीं।" इसका क्या मतलब है?

जवाबों:


207

System.exit()कार्यक्रम के पूरा होने से पहले शटडाउन हुक चलाने के लिए इस्तेमाल किया जा सकता है । यह बड़े कार्यक्रमों में शटडाउन को संभालने का एक सुविधाजनक तरीका है, जहां कार्यक्रम के सभी भाग एक दूसरे के बारे में नहीं जान सकते (और नहीं करना चाहिए)। फिर, अगर कोई छोड़ना चाहता है, तो वह बस कॉल कर सकता है System.exit(), और शटडाउन हुक (यदि ठीक से सेट हो) सभी आवश्यक शटडाउन समारोह जैसे कि फाइलें बंद करना, संसाधन जारी करना आदि का ध्यान रखें।

"यह विधि सामान्य रूप से कभी नहीं लौटती है।" इसका मतलब यह है कि विधि वापस नहीं आएगी; एक बार एक धागा वहाँ चला जाता है, यह वापस नहीं आएगा।

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

किसी कारण से शटडाउन हुक एक अघोषित और गलत समझा गया तंत्र है, और लोग अपने कार्यक्रमों को छोड़ने के लिए सभी तरह के मालिकाना कस्टम हैक के साथ पहिया को फिर से मजबूत कर रहे हैं। मैं शटडाउन हुक का उपयोग करने के लिए प्रोत्साहित करेगा; यह सब वहाँ मानक रनटाइम में है जो आप वैसे भी उपयोग करेंगे।


10
"यह विधि सामान्य रूप से कभी नहीं लौटती है।" इसका मतलब यह है कि विधि वापस नहीं आएगी; एक बार एक धागा वहाँ चला जाता है, यह वापस नहीं आएगा। विशेष रूप से ध्यान दें कि इसका मतलब है कि आप एक ऐसी प्रणाली का परीक्षण नहीं कर सकते हैं जो System.exit (0) कॉल करता है ...
Bill Michell

5
-1 गलत है। अगर JVM सामान्य रूप से समाप्त हो जाता है, तो कोई भी शट डाउन हुक चलेगा, भले ही यह System.exit या मुख्य () की समाप्ति के कारण हो। देखें zx81 / doku / java / javadoc / j2se1.5.0 / docs / api / java / lang /…
sleske

31
@ स्लेस्के: मुख्य () की समाप्ति पर्याप्त नहीं है यदि आसपास अन्य गैर-डेमॉन थ्रेड हैं। जब तक आप स्पष्ट रूप से System.exit () को कॉल नहीं करते, तब तक अंतिम गैर-डीमन थ्रेड समाप्त होने के बाद ही शटडाउन शुरू किया जाता है। यह स्पष्ट रूप से रनटाइम प्रलेखन में कहा गया है।
जूनस पुलका

3
ध्यान दें कि यदि आपका शटडाउन हुक बदले में उस धागे पर निर्भर करता है जिसे System.exit कहा जाता है, तो आप गतिरोध करेंगे।
djechlin

8
कुछ जोड़ने के लिए, अगर किसी ने एक रनटाइम रुकता है, तो शटडाउन हुक नहीं चलेगा ( Runtime.getRuntime().halt())
दुष्ट

50

उस मामले में, इसकी जरूरत नहीं है। कोई अतिरिक्त थ्रेड शुरू नहीं किया गया है, आप बाहर निकलने का कोड नहीं बदल रहे हैं (जो कि 0 में चूक) - मूल रूप से यह व्यर्थ है।

जब डॉक्स कहते हैं कि विधि सामान्य रूप से कभी नहीं लौटती है, तो इसका मतलब है कि कोड की बाद की रेखा प्रभावी रूप से पहुंच से बाहर है, भले ही संकलक को पता हो:

System.exit(0);
System.out.println("This line will never be reached");

या तो एक अपवाद फेंक दिया जाएगा, या वीएम लौटने से पहले समाप्त कर देगा। यह "सिर्फ वापसी" कभी नहीं होगा।

System.exit()IME कॉल करने के लायक होना बहुत दुर्लभ है । अगर आप कमांड लाइन टूल लिख रहे हैं तो यह समझ में आ सकता है, और आप केवल एक अपवाद फेंकने के बजाय निकास कोड के माध्यम से एक त्रुटि का संकेत देना चाहते हैं ... लेकिन मुझे याद नहीं है कि पिछली बार मैंने इसे सामान्य उत्पादन कोड में कैसे इस्तेमाल किया था ।


2
संकलक को क्यों नहीं पता है? क्या System.exit () वारंट विशिष्ट पहचान कोड के लिए पर्याप्त नहीं है?
बार्ट वैन ह्युकेलोम

3
@ बर्ट: नहीं, मुझे ऐसा नहीं लगता। इस तरह की चीजों के लिए भाषा में विशेष मामलों को रखना बहुत कम लाभ के साथ भाषा की जटिलता को जोड़ता है।
जॉन स्कीट

मैंने सोचा कि "सामान्य रूप से कभी नहीं लौटता" बयान के "अचानक समापन" के साथ करना था। (जेएलएस सेक्शन 14.1)। क्या मै गलत हु?
aioobe

@ वायो: नहीं, तुम सही हो। System.exit()सामान्य रूप से कभी पूरा नहीं होगा - यह हमेशा या तो एक अपवाद के साथ पूरा होगा, या वीएम शट डाउन के साथ (जो वास्तव में जेएलएस में कवर नहीं है)।
जॉन स्कीट

1
@ डीकचकर: आपको क्या लगता है? कॉलिंग शेल (या जो भी) को इंगित करने के लिए इसे 0 के अलावा किसी अन्य मान के साथ कॉल करना पूरी तरह से उचित है, जो प्रोग्राम में त्रुटि आई है।
जॉन स्कीट

15

यह विधि कभी नहीं लौटती है क्योंकि यह दुनिया का अंत है और आपके किसी भी कोड को आगे निष्पादित नहीं किया जाएगा।

आपका आवेदन, आपके उदाहरण में, कोड में समान स्थान पर वैसे भी बाहर निकल जाएगा, लेकिन, यदि आप System.exit का उपयोग करते हैं। आपके पास वातावरण कोड को कस्टम कोड वापस करने का विकल्प है, जैसे, कहते हैं

System.exit(42);

आपके निकास कोड का उपयोग कौन करने जा रहा है? एक स्क्रिप्ट जिसे एप्लिकेशन कहा जाता है। विंडोज, यूनिक्स और अन्य सभी स्क्रिप्ट योग्य वातावरण में काम करता है।

क्यों एक कोड वापस? "मैं सफल नहीं हुआ" जैसी चीजों को कहने के लिए, "डेटाबेस ने जवाब नहीं दिया"।

यह देखने के लिए कि मान को एक निकास कोड कैसे प्राप्त करें और इसका उपयोग यूनिक्स शेल स्क्रिप्ट या विंडोज़ cmd स्क्रिप्ट में करें, आप इस साइट पर इस उत्तर की जांच कर सकते हैं


14

System.exit(0)JVM को समाप्त करता है। इस तरह के सरल उदाहरणों में, अंतर को समझना मुश्किल है। पैरामीटर को ओएस में वापस भेज दिया जाता है और सामान्य रूप से असामान्य समाप्ति (जैसे किसी प्रकार की घातक त्रुटि) को इंगित करने के लिए उपयोग किया जाता है, इसलिए यदि आप एक बैच फ़ाइल या शेल स्क्रिप्ट से जावा कहते हैं, तो आप इस मूल्य को प्राप्त करने और एक विचार प्राप्त करने में सक्षम होंगे। अगर आवेदन सफल रहा।

यदि आप System.exit(0)किसी एप्लिकेशन सर्वर पर तैनात एप्लिकेशन पर कॉल करते हैं, तो इसके बारे में सोचें, तो यह काफी प्रभावी होगा ।


12

उन अनुप्रयोगों में जिनमें जटिल शटडाउन हुक हो सकते हैं, इस विधि को अज्ञात धागे से नहीं बुलाया जाना चाहिए। System.exitकभी भी सामान्य रूप से बाहर नहीं निकलता क्योंकि जेवीएम समाप्त होने तक कॉल ब्लॉक हो जाएगी। यह ऐसा है जैसे कि जो भी कोड चल रहा है, उसे समाप्त करने से पहले पावर प्लग उस पर खींच लिया गया है। कॉलिंग System.exitप्रोग्राम के शटडाउन हुक शुरू करेगा और जो भी कॉल System.exitप्रोग्राम समाप्ति तक अवरुद्ध होगा। इसका यह अर्थ है कि यदि शटडाउन हुक बदले में उस कार्य को सबमिट करता है जिसमें System.exitसे कॉल किया गया था, तो प्रोग्राम गतिरोध करेगा।

मैं निम्नलिखित के साथ अपने कोड में इसे संभाल रहा हूं:

public static void exit(final int status) {
    new Thread("App-exit") {
        @Override
        public void run() {
            System.exit(status);
        }
    }.start();
}

मेरे पास यह मुद्दा भी था जहां System.exit वास्तव में JVM को समाप्त नहीं करेगा। यह केवल कुछ शर्तों के तहत खुश है। थ्रेडप्ल / शटडाउन हैंडलर्स शटडाउन को बंद कर रहे हैं, इसके बारे में मुझे कोई जानकारी नहीं दी गई थी। टिप्पणी में वर्णित कोड का उपयोग करने से मुझे इसे हल करने में मदद मिली!
काई

7

हालांकि उत्तर वास्तव में मददगार था, लेकिन कुछ ने इसे और अधिक विस्तार से कैसे याद किया। मुझे आशा है कि नीचे दिए गए उत्तर के अलावा, जावा में शटडाउन प्रक्रिया को समझने में मदद मिलेगी:

  1. एक अर्दली * शटडाउन में, जेवीएम पहले सभी पंजीकृत शटडाउन हुक शुरू करता है। शटडाउन हुक अनस्टर्ड थ्रेड हैं जो Runtime.addShutdownHook के साथ पंजीकृत हैं।
  2. जेवीएम उस आदेश पर कोई गारंटी नहीं देता है जिसमें शटडाउन हुक शुरू किए जाते हैं। यदि कोई भी एप्लिकेशन थ्रेड्स (डेमॉन या नोंडोमन) अभी भी शटडाउन समय पर चल रहे हैं, तो वे शटडाउन प्रक्रिया के साथ समवर्ती रूप से चलते रहते हैं
  3. जब सभी शटडाउन हुक पूरा हो गए हैं, तो JVM फाइनल चलाने के लिए चुन सकता है यदि runFinalizersOnExit सच है, और फिर रुक जाता है।
  4. जेवीएम किसी भी एप्लिकेशन थ्रेड को बंद करने या बाधित करने का कोई प्रयास नहीं करता है जो अभी भी शटडाउन समय पर चल रहे हैं; जब जेवीएम अंततः रुक जाता है तो उन्हें अचानक समाप्त कर दिया जाता है।
  5. यदि शटडाउन हुक या फाइनल पूरा नहीं होता है, तो क्रमिक शटडाउन प्रक्रिया "हैंग" होती है और जेवीएम को अचानक बंद होना चाहिए।
  6. अचानक शटडाउन में, जेवीएम को जेवीएम को रोकने के अलावा कुछ भी करने की आवश्यकता नहीं है; शटडाउन हुक नहीं चलेंगे।

पुनश्च: जेवीएम एक व्यवस्थित या अचानक तरीके से बंद हो सकता है।

  1. अंतिम "सामान्य" (nondaemon) थ्रेड समाप्त होने पर एक व्यवस्थित शटडाउन शुरू किया जाता है, कोई व्यक्ति System.exit, या अन्य प्लेटफ़ॉर्म-विशिष्ट साधनों (जैसे कि SIGINT भेजना या Ctrl-C मारना) को कॉल करता है।
  2. जबकि ऊपर JVM को बंद करने के लिए मानक और पसंदीदा तरीका है, इसे अचानक रनटाइम द्वारा कॉल करके या ऑपरेटिंग सिस्टम के माध्यम से JVM प्रक्रिया को मारकर (जैसे कि SIGKILL भेजकर) बंद किया जा सकता है।

7

System.exit(0)इन कारणों से किसी को कॉल नहीं करना चाहिए :

  1. यह एक छिपे हुए "गोटो" और "गोटो" का नियंत्रण प्रवाह है। इस संदर्भ में हुक पर भरोसा एक मानसिक मानचित्रण है जिसे टीम के प्रत्येक डेवलपर को जानना होगा।
  2. कार्यक्रम को "सामान्य रूप से" छोड़ना ऑपरेटिंग सिस्टम को समान निकास कोड प्रदान करता है, System.exit(0)इसलिए यह बेमानी है।

    यदि आपका कार्यक्रम "सामान्य रूप से" नहीं छोड़ सकता है, तो आप अपने विकास [डिजाइन] पर नियंत्रण खो चुके हैं। आपके पास हमेशा सिस्टम स्थिति का पूर्ण नियंत्रण होना चाहिए।

  3. प्रोग्रामिंग समस्याएं जैसे कि चलने वाले धागे जो सामान्य रूप से बंद नहीं होते हैं, छिपे हुए हो जाते हैं।
  4. आप असामान्य रूप से थ्रेड को बाधित करने वाले एक असंगत अनुप्रयोग स्थिति का सामना कर सकते हैं। (# 3 का संदर्भ लें)

वैसे: 0 से अन्य रिटर्न कोड वापस करने से कोई मतलब नहीं है अगर आप असामान्य प्रोग्राम समाप्ति का संकेत देना चाहते हैं।


2
"आपके पास हमेशा सिस्टम स्थिति का पूर्ण नियंत्रण होना चाहिए।" यह जावा में बस संभव नहीं है। IoC चौखटे और अनुप्रयोग सर्वर केवल 2 बहुत लोकप्रिय और व्यापक रूप से उपयोग किए जाने वाले तरीके हैं जो आप सिस्टम राज्य के अपने नियंत्रण को छोड़ देते हैं। और यह पूरी तरह से ठीक है।
मुहल्ज़

कृपया अपने एप्लिकेशन सर्वर में System.exit (0) निष्पादित करें और मुझे अपने सर्वर व्यवस्थापक की प्रतिक्रियाओं के बारे में बताएं ... आपने इस प्रश्न और मेरे उत्तर के विषय को याद किया।
oopexpert

शायद मैं पर्याप्त स्पष्ट नहीं था। आपके पास हमेशा उस सिस्टम स्थिति का पूर्ण नियंत्रण होना चाहिए जिसके लिए आप जिम्मेदार हैं। हां, कुछ जिम्मेदारियों को एप्लिकेशन सर्वर और IoC में स्थानांतरित कर दिया गया था। लेकिन मैं उस बारे में बात नहीं कर रहा था।
oopexpert

5

System.exit की जरूरत है

  • जब आप एक गैर-0 त्रुटि कोड वापस करना चाहते हैं
  • जब आप अपने प्रोग्राम को कहीं से बाहर करना चाहते हैं जो मुख्य नहीं है ()

आपके मामले में, यह ठीक वैसा ही काम करता है जैसा कि साधारण रिटर्न-मेन से होता है।


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

@ बर्ट: आप जो वर्णन करते हैं , वह प्रोग्राम को बंद करने के संभावित तरीकों में से एक है, न कि उचित तरीका । सभी धागे को अच्छी तरह से बंद करने के लिए शटडाउन हुक का उपयोग करने में कुछ भी गलत नहीं है। और शटडाउन हुक के साथ लॉन्च किया जाता है exit। एकमात्र विकल्प नहीं है, लेकिन निश्चित रूप से विचार करने लायक विकल्प है।
जूनस पुलका

लेकिन मैं डॉक्स से इकट्ठा होता हूं, शटडाउन हुक बहुत नाजुक होते हैं और आपके पास उन्हें करने के लिए बहुत समय नहीं होता है। हर तरह से, ओएस शटडाउन या कुछ के मामले में उन्हें अच्छी तरह से छोड़ने के लिए उपयोग करें, लेकिन यदि आप System.exit () को कॉल करते हैं तो मुझे लगता है कि इससे पहले शटडाउन कोड करना बेहतर होगा (जिसके बाद आप शायद नहीं करेंगे जरूरत System.exit () किसी भी अधिक)
बार्ट वैन Heukelom

1
शटडाउन हुक के पास हर समय वे खत्म करने के लिए ले जाते हैं। सभी हुक वापस आने से पहले VM को रोका नहीं गया है। वीएम को शटडाउन हुक को पंजीकृत करने से रोकने से वास्तव में रोकना संभव है जो निष्पादित करने में बहुत समय लगता है। लेकिन बेशक विभिन्न, वैकल्पिक तरीकों से शटडाउन अनुक्रम करना संभव है।
जूनस पुलका

यदि अन्य गैर-डीमन धागे हैं तो मुख्य से वापस आना बंद नहीं होगा।
djechlin

4

जावा लैंग्वेज स्पेसिफिकेशन का कहना है कि

कार्यक्रम से बाहर निकलें

एक कार्यक्रम अपनी सारी गतिविधि समाप्त कर देता है और दो चीजों में से एक होने पर बाहर निकलता है:

सभी धागे जो डेमन थ्रेड नहीं हैं वे समाप्त हो जाते हैं।

कुछ धागे वर्ग रनटाइम या क्लास सिस्टम के निकास विधि को आमंत्रित करते हैं , और सुरक्षा प्रबंधक द्वारा निकास संचालन की मनाही नहीं है।

इसका मतलब है कि आपको इसका उपयोग तब करना चाहिए जब आपके पास बड़ा कार्यक्रम हो (अच्छी तरह से, कम से कम इस एक से बड़ा) और इसका निष्पादन समाप्त करना चाहते हैं।


3

यदि आपके पास JVM में एक और प्रोग्राम चल रहा है और आप System.exit का उपयोग करते हैं, तो वह दूसरा प्रोग्राम भी बंद हो जाएगा। उदाहरण के लिए कल्पना करें कि आप क्लस्टर नोड पर जावा जॉब चलाते हैं और जावा प्रोग्राम जो क्लस्टर नोड का प्रबंधन करता है, उसी VVM में चलता है। यदि नौकरी System.exit का उपयोग करेगी तो यह न केवल नौकरी छोड़ देगा, बल्कि "पूर्ण नोड को बंद कर देगा"। आप उस क्लस्टर नोड में दूसरी नौकरी नहीं भेज पाएंगे क्योंकि प्रबंधन कार्यक्रम गलती से बंद हो गया है।

इसलिए, यदि आप उसी JVM के भीतर किसी अन्य जावा प्रोग्राम से अपने प्रोग्राम को नियंत्रित करने में सक्षम होना चाहते हैं, तो System.exit का उपयोग न करें।

System.exit का उपयोग करें यदि आप उद्देश्य के लिए पूरा JVM बंद करना चाहते हैं और यदि आप अन्य संभावनाओं में वर्णित संभावनाओं का लाभ उठाना चाहते हैं (उदाहरण के लिए हुक बंद करें: जावा शटडाउन हुक , कमांड लाइन के लिए गैर-शून्य रिटर्न मान कॉल: कैसे Windows बैच फ़ाइल में एक जावा प्रोग्राम की निकास स्थिति प्राप्त करने के लिए )।

इसके अलावा Runtime अपवाद पर एक नज़र है: System.exit (संख्या) या मुख्य से एक RuntimeException फेंक?

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