स्प्रिंग एप्लिकेशनकोटेक्स्ट - संसाधन रिसाव: 'संदर्भ' कभी बंद नहीं होता है


94

एक स्प्रिंग एमवीसी एप्लिकेशन में, मैं निम्नलिखित दृष्टिकोणों का उपयोग करके सेवा वर्गों में से एक में एक वैरिएबल को शुरू करता हूं:

ApplicationContext context = 
         new ClassPathXmlApplicationContext("META-INF/userLibrary.xml");
service = context.getBean(UserLibrary.class);

UserLibrary एक 3 पार्टी की उपयोगिता है जिसका उपयोग मैं अपने आवेदन में कर रहा हूँ। उपरोक्त कोड 'संदर्भ' चर के लिए एक चेतावनी उत्पन्न करता है। चेतावनी नीचे दी गई है:

Resource leak: 'context' is never closed

मैं चेतावनी नहीं समझता। जैसा कि एप्लिकेशन स्प्रिंग MVC अनुप्रयोग है, मैं वास्तव में संदर्भ को बंद / नष्ट नहीं कर सकता क्योंकि मैं सेवा चला रहा हूं, जबकि एप्लिकेशन चल रहा है। वास्तव में चेतावनी मुझे क्या बताने की कोशिश कर रही है?


2
मैं इस बात से उत्सुक हूं कि आप स्प्रिंग एमवीसी द्वारा बूट किए गए एप्लिकेशन संदर्भ के भीतर बीन बनाने के विरोध में एक और एप्लिकेशन संदर्भ क्यों बना रहे हैं
केविन बोवर्सॉक्स

इस सूत्र को देखें stackoverflow.com/questions/14184177/… एक स्पष्टीकरण के लिए कि क्यों मुझे एक नया कंटेनर बनाना था।
जिग्गी

यह दिखावा कब दिखाया जाता है: जब आप संदर्भ बनाते हैं?
राल्फ

मैंने इसे केवल ग्रहण (पीले रंग में रेखांकित) में देखा था। जब मैंने एप्लिकेशन चलाया तो मैंने केवल लॉग की जांच की थी लेकिन मुझे चेतावनी दिखाई नहीं दे रही है।
जिग्गी

जवाबों:


92

चूंकि ऐप का संदर्भ एक है ResourceLoader(यानी I / O संचालन) यह उन संसाधनों का उपभोग करता है जिन्हें किसी बिंदु पर मुक्त करने की आवश्यकता होती है। यह भी AbstractApplicationContextलागू होता है जिसमें से एक है Closable। इस प्रकार, यह एक close()विधि है और एक कोशिश के साथ संसाधनों के बयान में इस्तेमाल किया जा सकता है ।

try (ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("META-INF/userLibrary.xml")) {
  service = context.getBean(UserLibrary.class);
}

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

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


मुझे लगता है कि समस्या का स्रोत वास्तव में यह है कि मैं एक अलग संदर्भ बना रहा हूं। चेतावनी को हल करने की कोशिश करने की तुलना में अतिरिक्त संदर्भ को हटाना शायद एक बेहतर विकल्प है। धन्यवाद।
जिग्गी

25
ध्यान देने योग्य बात: जबकि आधार ApplicationContextपूर्णांक close()विधि प्रदान नहीं करता है , ConfigurableApplicationContext(जो ClassPathXmlApplicationContextलागू करता है) Closeableबूट करने के लिए करता है और विस्तारित होता है, इसलिए आप जावा 7 कोशिश-के साथ संसाधन प्रतिमान का उपयोग कर सकते हैं।
kbolino

@kbolino। कोशिश-के साथ संसाधनों का कथन यह सुनिश्चित करता है कि प्रत्येक संसाधन कथन के अंत में बंद हो।
ruruskyi

1
@kbolino यह भी देखें: stackoverflow.com/questions/14423980/…
Raedwald

3
+1 से @ kbolino की टिप्पणी यहाँ, क्योंकि मैं अपने चर को घोषित कर रहा था ApplicationContextऔर अपना सिर खुजला रहा था कि क्यों मुझे चेतावनी मिल रही है जब वहाँ कोई करीबी तरीका उपलब्ध नहीं हुआ ...
Periata Breatta

40

close()ApplicationContextइंटरफ़ेस में परिभाषित नहीं है ।

चेतावनी से सुरक्षित रूप से छुटकारा पाने का एकमात्र तरीका निम्नलिखित है

ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(...);
try {
    [...]
} finally {
    ctx.close();
}

या, जावा 7 में

try(ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(...)) {
    [...]
}

मूल अंतर यह है कि चूंकि आप संदर्भ को स्पष्ट रूप से तुरंत उपयोग करते हैं (अर्थात के उपयोग से new) आपको पता है कि आप जिस कक्षा में तात्कालिकता कर रहे हैं, इसलिए आप अपने चर को तदनुसार परिभाषित कर सकते हैं।

यदि आप AppContext (यानी स्प्रिंग द्वारा प्रदान किए गए एक का उपयोग करके) को इंस्टेंट नहीं कर रहे थे, तो आप इसे बंद नहीं कर सकते थे।


6
बार-बार गलत कोशिश ... अंत में दूसरों को सिखाया जाता है ... new ClassPathXmlApplicationContext(...);कोशिश-ब्लॉक के बाहर होना चाहिए। फिर अशक्त जाँच की कोई आवश्यकता नहीं है। यदि कंस्ट्रक्टर अपवाद फेंकता है तो ctxअशक्त है और finallyब्लॉक को नहीं बुलाया गया है (क्योंकि अपवाद को कोशिश-ब्लॉक के बाहर फेंक दिया गया था)। अगर कंस्ट्रक्टर ने एक अपवाद नहीं फेंका, तो tryब्लॉक में प्रवेश किया जाता है और ctxअशक्त नहीं हो सकता है, इसलिए कोई आवश्यकता नहीं है, फिर एक शून्य-जांच के लिए।
कायर

यह उत्तर खराब है, आपकी कोशिश के साथ एक वास्तविक समस्या है अंत में ब्लॉक। बस परीक्षण किया गया है, लेकिन काम नहीं कर रहा है।
HDJEMAI

12

एक साधारण कलाकार समस्या हल करता है:

((ClassPathXmlApplicationContext) fac).close();

6

जैसा कि अनुप्रयोग संदर्भ में ClassPathXmlApplicationContext का एक उदाहरण है और उसी के पास एक () विधि है। मैं बस appContext वस्तु कास्ट और नीचे के रूप में बंद () विधि आह्वान करेंगे।

ApplicationContext appContext = new ClassPathXmlApplicationContext("spring.xml");
//do some logic
((ClassPathXmlApplicationContext) appContext).close();

यह संसाधन रिसाव चेतावनी को ठीक करेगा।


4

इसे इस्तेमाल करे। आपको आवेदन पत्र बंद करने के लिए कास्ट लगाने की आवश्यकता है।

   ClassPathXmlApplicationContext ctx = null;
      try {
         ctx = new ClassPathXmlApplicationContext(...);
            [...]
             } finally {
              if (ctx != null)
                  ((AbstractApplicationContext) ctx).close();       
      }

3

यहां तक ​​कि मेरे पास ठीक वैसी ही चेतावनी थी, जैसा कि मैंने किया था ApplicationContext, मुख्य समारोह के बाहर घोषित किया गया था private staticऔर टा-डा, समस्या तय हो गई थी।

public class MainApp {
    private static ApplicationContext context;

    public static void main(String[] args) {
        context = new ClassPathXmlApplicationContext("Beans.xml");

        HelloWorld objA = (HelloWorld) context.getBean("helloWorld");

        objA.setMessage("I'm object A");
        objA.getMessage();

        HelloWorld objB = (HelloWorld) context.getBean("helloWorld");
        objB.getMessage();
    }
}

8
यह चेतावनी समस्या को हल करता है लेकिन वास्तविक मुद्दा नहीं है जो संदर्भ को खुला छोड़ रहा है और रिसाव का कारण बनता है। आप एक @SupressWarningsएनोटेशन के साथ भी ऐसा कर सकते हैं , लेकिन रूट समस्या को हल करने के लिए बेहतर है, आपको नहीं लगता?
Xtreme बाइकर

हाँ आप सही कह रहे हैं .. यह मेरे लिए उस समय सिर्फ एक समाधान था।
एलिसियम

यह एक अच्छा जवाब नहीं है। चूँकि वास्तविक मुद्दा वही रहता है, अर्थात संसाधन रिसाव होता है, संदर्भ कभी बंद नहीं होता है।
एचडीजेईएआई

2

कास्टिंग इस मुद्दे के लिए सही समाधान है। मैंने नीचे की रेखा का उपयोग करके उसी मुद्दे का सामना किया। ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);

चेतावनी को हल करने के लिए बस ctxनीचे की तरह ऑब्जेक्ट को डाउन करें और फिर इसे बंद करें। ((AnnotationConfigApplicationContext) ctx).close();


1

विन्यास करने के लिए संदर्भ को डाउन करे।

((ConfigurableApplicationContext)context).close();

((ConfigurableApplicationContext)(context)).close();यह सही जवाब हो सकता है
भार्गव मोदी

Amit28 से उत्तर सही है। उत्तर उपयोगी क्यों नहीं है?
रूडी विंसर्स

1
Object obj = context.getBean("bean");
if(bean instanceof Bean) {
    Bean bean = (Bean) obj;
}

मेरे मामले में रिसाव गायब हो गया


1

इसने मेरे लिए सबसे अच्छा काम किया।

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class Test {

     private static ApplicationContext con;

     public static void main(String[] args) {

         con = new ClassPathXmlApplicationContext("config.xml");

         Employee ob = (Employee) con.getBean("obj");
         System.out.println("Emp Id " + ob.getEmpno());
         System.out.println("Emp name " + ob.getEmpname());
    }
}

0

यदि आप ClassPathXmlApplicationContext का उपयोग कर रहे हैं तो आप उपयोग कर सकते हैं

((ClassPathXmlApplicationContext) context).close();

संसाधन रिसाव समस्या को बंद करने के लिए।

यदि आप AbstractApplicationContext का उपयोग कर रहे हैं तो आप इसे करीबी विधि से डाल सकते हैं।

((AbstractApplicationContext) context).close();

यह एप्लिकेशन में उपयोग करने वाले संदर्भ के प्रकार पर निर्भर करता है।


0
import org.springframework.context.ConfigurableApplicationContext;

((ConfigurableApplicationContext)ctx).close();

2
क्या आप इस बारे में विस्तार से सोच सकते हैं कि आप इस प्रश्न का उत्तर क्यों देते हैं?
जेएन ब्रोकेस्ट्रा

ClassPathXMLApplicationContext सुपर क्लास इम्प्लीमेंटेबलApplicationContext जिसमें क्लोज़ () विधि शामिल है। हम संदर्भ को टाइप () विधि को कॉल करने के लिए ConfigurableApplicationContext में टाइप कर सकते हैं, यह संसाधनों को मुक्त करता है। बस हम भी कर सकते हैं ((ClassPathXmlApplicationContext) ctx) .close ();
सुसेन्द्रन P

0

आप संदर्भ को एक स्थिर चर बनाते हैं, जिसका अर्थ है कि संदर्भ कक्षा में सभी स्थिर तरीकों के लिए उपलब्ध है, और मुख्य विधि के दायरे तक सीमित नहीं है। इसलिए उपकरण यह नहीं मान सकता है कि इसे विधि के अंत में बंद किया जाना चाहिए, इसलिए यह अब चेतावनी जारी नहीं करता है।

public class MainApp {
    private static ApplicationContext context;
    public static void main(String[] args) {
          context = 
                 new ClassPathXmlApplicationContext("Beans.xml");

          HelloWorld obj = (HelloWorld) context.getBean("helloWorld");

          obj.getMessage();

       }
}

0

हां, इंटरफ़ेस ApplicationContextमें close()विधि नहीं है , इसलिए मैं स्पष्ट रूप से AbstractApplicationContextउस closeपद्धति का उपयोग करने के लिए वर्ग का उपयोग करना पसंद करता हूं और यहां आप XMLटाइप के बजाय एनोटेशन का उपयोग करके अपने स्प्रिंग एप्लिकेशन कॉन्फ़िगरेशन वर्ग का उपयोग कर सकते हैं ।

AbstractApplicationContext context = new AnnotationConfigApplicationContext(SpringAppConfig.class);
Foo foo = context.getBean(Foo.class);

//do some work with foo

context.close();

Resource leak: 'context' is never closedअब आपकी चेतावनी समाप्त हो गई है।


0

इसका एक सरल समाधान है कि बस पुस्तकालयों में कोर जार इनपुट करें, इस लिंक पर [वसंत के लिए कोर जार फ़ाइलों को डाउनलोड करें] [1] [१]: https://static.javatpoint.com/src/sp/spcorejars। ज़िप


1
कृपया मार्कडाउन डॉक्स की जांच करें और पूर्वावलोकन का उपयोग करें, ऐसा लगता है कि आपका URL छोटा हो गया है।
सिंह

-1

कॉन्फ़िगर करने योग्यApplicationContext इंटरफ़ेस में विधि को बंद कर दिया गया है, इसलिए आप इसे प्राप्त करने के लिए सबसे अच्छा कर सकते हैं:

ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(
                "/app-context.xml");

// Use the context...

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