संसाधन रिसाव: 'में' कभी बंद नहीं होता है


84

निम्नलिखित कोड में ग्रहण मुझे वार्मिंग "संसाधन रिसाव: 'को' कभी बंद नहीं होता" क्यों देता है?

public void readShapeData() {
        Scanner in = new Scanner(System.in);
        System.out.println("Enter the width of the Rectangle: ");
        width = in.nextDouble();
        System.out.println("Enter the height of the Rectangle: ");
        height = in.nextDouble();

जवाबों:


69

क्योंकि आप अपने स्कैनर को बंद नहीं करते हैं

in.close();

39
यह Scannerचेतावनी को बंद और चुप कर देगा, लेकिन यह भी बंद हो जाएगा System.inजो आमतौर पर वांछनीय नहीं है।
स्टुअर्ट कुक

@StuartCook +1। नजर रखने के लिए कुछ।
informatik01

7
हमें स्कैनर को बंद करने की आवश्यकता क्यों है? "संसाधन रिसाव" से क्या अभिप्राय है?
इरान मोराद

1
@nogard: यह आपका उत्तर वास्तव में सहायक है .. लेकिन जब मैं incl () का उपयोग करता हूं; .. फिर से यह दिखाता है कि इसे हल नहीं किया जा सकता है .. मेरे पास अपवाद हैंडलिंग के बिना एक कोड है .. धन्यवाद
पीसी

3
@StuartCook, आप यह उल्लेख करना भूल गए कि बंद System.inकरना आमतौर पर वांछनीय क्यों नहीं है। यह इसलिए है क्योंकि आप इसे फिर से नहीं पढ़ पाएंगे। अर्थात। java.util.NoSuchElementException: No line foundयदि आप (new Scanner(System.in)).nextLine()उदाहरण के लिए कॉल करने का प्रयास करते हैं तो आपको मिलेगा ।
पेट्र बोडनार

55

जैसा कि अन्य लोगों ने कहा है, आपको आईओ कक्षाओं पर 'करीब' कॉल करने की आवश्यकता है। मैं जोड़ूंगा कि यह कोशिश का उपयोग करने के लिए एक उत्कृष्ट स्थान है - अंत में इस तरह से कोई पकड़ के साथ ब्लॉक करें:

public void readShapeData() throws IOException {
    Scanner in = new Scanner(System.in);
    try {
        System.out.println("Enter the width of the Rectangle: ");
        width = in.nextDouble();
        System.out.println("Enter the height of the Rectangle: ");
        height = in.nextDouble();
    } finally {
        in.close();
    }
}

यह सुनिश्चित करता है कि आपका स्कैनर हमेशा बंद रहता है, उचित संसाधन सफाई की गारंटी देता है।

समान रूप से, जावा 7 या अधिक में, आप "ट्राय-विथ-रिसोर्स" सिंटैक्स का उपयोग कर सकते हैं:

try (Scanner in = new Scanner(System.in)) {
    ... 
}

2
संसाधन रिसाव से क्या मतलब है और यह मुझे कैसे प्रभावित करेगा?
इरान मोराद

7
@ बोरैट - "रिसोर्स लीक" से तात्पर्य है कि कुछ सिस्टम रिसोर्स (आमतौर पर मेमोरी) बेकार हो रहे हैं या बेकार हो रहे हैं। जब आप अपने प्रोग्राम के सामान्य संचालन के दौरान आउटऑफ़मेरी एरर्स प्राप्त करना शुरू करते हैं तो आमतौर पर यह आपको प्रभावित करेगा।
एरिक लिंडौअर

धन्यवाद इरिक। मुझे पता है कि आप एक अनंत लूप में खुद को एक स्ट्रिंग जोड़कर त्रुटि का कारण बन सकते हैं। मुझे यकीन नहीं है कि कैसे एक स्कैनर उस त्रुटि का कारण बन सकता है।
इरान मोराद

4
एक कोशिश के साथ संसाधनों के बारे में क्या?
डेनिस मेंग

धन्यवाद डेनिस, जोड़ा।
एरिक लिंडौएर

12

यह सुनिश्चित करने के लिए आपको in.close()एक finallyब्लॉक में कॉल की आवश्यकता है।

ग्रहण के दस्तावेज़ीकरण से, यहाँ बताया गया है कि यह इस समस्या को हल करता है ( जोर मेरा):

इंटरफ़ेस java.io.Closeable (JDK 1.5 के बाद से) और java.lang.AutoCloseable (JDK 1.7 के बाद से) को लागू करने वाले वर्गों को बाहरी संसाधनों का प्रतिनिधित्व करने के लिए माना जाता है, जिन्हें विधि बंद () का उपयोग करके बंद किया जाना चाहिए, जब उन्हें अब ज़रूरत नहीं है।

एक्लिप्स जावा कंपाइलर विश्लेषण करने में सक्षम है कि क्या इस प्रकार के कोड का उपयोग इस नीति का पालन करता है।

...

कंपाइलर "संसाधन रिसाव: 'स्ट्रीम' कभी बंद नहीं होता है।

पूर्ण विवरण यहाँ


7

यह आपको बता रहा है कि आपको उस स्कैनर को बंद करने की आवश्यकता है जिस पर आपने तुरंत हस्ताक्षर किया System.inथा Scanner.close()। आम तौर पर हर पाठक को बंद होना चाहिए।

ध्यान दें कि यदि आप बंद करते हैं System.in, तो आप इसे फिर से नहीं पढ़ पाएंगे। आप Consoleक्लास भी देख सकते हैं ।

public void readShapeData() {
    Console console = System.console();
    double width = Double.parseDouble(console.readLine("Enter the width of the Rectangle: "));
    double height = Double.parseDouble(console.readLine("Enter the height of the Rectangle: "));
    ...
}

3
ध्यान दें कि System.console()ग्रहण के माध्यम से एप्लिकेशन चलाते समय उपलब्ध नहीं है, जो विकास के दौरान परेशानी हो सकती है।
स्टुअर्ट कुक

6

यदि आप JDK7 या 8 का उपयोग कर रहे हैं, तो आप संसाधनों के साथ ट्राइ-कैच का उपयोग कर सकते हैं। यह स्वचालित रूप से स्कैनर को बंद कर देगा।

try ( Scanner scanner = new Scanner(System.in); )
  {
    System.out.println("Enter the width of the Rectangle: ");
    width = scanner.nextDouble();
    System.out.println("Enter the height of the Rectangle: ");
    height = scanner.nextDouble();
  }
catch(Exception ex)
{
    //exception handling...do something (e.g., print the error message)
    ex.printStackTrace();
}

ध्यान दें कि कैच क्लॉज़ अनिवार्य नहीं है। यदि आप केवल अपवाद की स्थिति में भी संसाधन को बंद करना सुनिश्चित करना चाहते हैं, लेकिन अपवादों के उपचार को छोड़ दें जैसा कि ओपी के मूल कोड (अर्थात्, बिल्कुल नहीं पकड़ा गया) को आप केवल tryदिखाए गए अनुसार उपयोग कर सकते हैं और एक catchखंड का उपयोग नहीं कर सकते हैं ।
user118967

5
// An InputStream which is typically connected to keyboard input of console programs

Scanner in= new Scanner(System.in);

उपरोक्त लाइन तर्क प्रणाली के साथ स्कैनर वर्ग के कंस्ट्रक्टर को आमंत्रित करेगी, और नवनिर्मित वस्तु का संदर्भ लौटाएगी।

यह एक इनपुट स्ट्रीम से जुड़ा है जो कीबोर्ड से जुड़ा है, इसलिए अब रन-टाइम में आप आवश्यक ऑपरेशन करने के लिए उपयोगकर्ता इनपुट ले सकते हैं।

//Write piece of code 

स्मृति रिसाव को दूर करने के लिए -

in.close();//write at end of code.


3

जोड़ना private static Scanner in;वास्तव में समस्या को ठीक नहीं करता है, यह केवल चेतावनी को साफ करता है। स्कैनर को स्थिर बनाने का मतलब यह हमेशा के लिए खुला रहता है (या जब तक कि क्लास अनलोड न हो जाए, जो लगभग "हमेशा के लिए" है)। संकलक आपको कोई चेतावनी नहीं देता है, क्योंकि आपने उससे कहा था कि "इसे हमेशा खुला रखें"। लेकिन यह वह नहीं है जो आप वास्तव में चाहते थे, क्योंकि आपको संसाधनों को जल्द से जल्द बंद कर देना चाहिए, क्योंकि आपको उनकी कोई आवश्यकता नहीं है।

एचटीएच, मैनफ्रेड।


2

आमतौर पर, I / O से निपटने वाली कक्षाओं के उदाहरणों को उनके साथ समाप्त होने के बाद बंद कर दिया जाना चाहिए। तो अपने कोड के अंत में आप जोड़ सकते हैं in.close()


2
private static Scanner in;

मैंने इसे निजी स्थिर स्कैनर वर्ग चर के रूप में घोषित करके तय किया। निश्चित नहीं है कि यह क्यों तय किया गया है, लेकिन यह वही है जो ग्रहण की सिफारिश की है।


5
आपने चेतावनी को म्यूट कर दिया लेकिन संसाधन रिसाव बनाया
zacheusz

1

स्कैनर बंद होना चाहिए। रीडर्स, स्ट्रीम ... और इस तरह की वस्तुओं को संसाधनों और एनोविड मेमोरी लीक से मुक्त करना एक अच्छा अभ्यास है; और अंत में ब्लॉक में यह सुनिश्चित करने के लिए कि वे बंद हैं भले ही उन वस्तुओं को संभालने के दौरान कोई अपवाद हो।


यह जवाब वास्तव में ओपी को यह जानने में मदद करता है कि उसे क्यों बात बंद करनी चाहिए। ज़रूर, वह डॉक्टर को पढ़ सकता है और " scanner.close()" देख सकता है , लेकिन यह उत्तर वास्तव में उसे समझने में मदद करता है कि क्या चल रहा है। + 1
हाइपरन्यूट्रिनो 3

1

ठीक है, गंभीरता से, कई मामलों में कम से कम, यह वास्तव में एक बग है। यह वी.एस. कोड में भी दिखाई देता है, और यह लिंटर नोटिंग है कि आप स्कैनर ऑब्जेक्ट को बंद किए बिना एन्कोडिंग स्कोप के अंत तक पहुंच गए हैं, लेकिन यह नहीं पहचानना कि सभी ओपन फाइल डिस्क्रिप्टर को बंद करना प्रक्रिया समाप्ति का हिस्सा है। कोई रिसोर्स लीक नहीं है क्योंकि रिसोर्सेस को खत्म करने के लिए रिसोर्स की सफाई की जाती है, और रिसोर्स को छोड़ दिया जाता है।



-1
in.close();
scannerObject.close(); 

यह Scannerचेतावनी को बंद और बंद कर देगा ।

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