जावा में कचरा संग्रह को कैसे मजबूर करें?


225

क्या जावा में कचरा संग्रह करना संभव है, भले ही यह करने के लिए मुश्किल हो? मैं जानता हूं System.gc();और Runtime.gc();वे केवल जीसी करने के लिए सुझाव देते हैं। मैं GC को कैसे मजबूर कर सकता हूं?


30
शायद आपको जीसी को मजबूर करने की आवश्यकता के लिए कुछ पृष्ठभूमि प्रदान करना उपयोगी होगा। आमतौर पर एक कचरा एकत्र भाषा में कलेक्टर को स्पष्ट रूप से कॉल करने के लिए यह बुरा अभ्यास है।
जस्टिन एथियर

3
एक दिया हुआ JVM कई कचरा संग्रहण विधियाँ प्रदान कर सकता है, प्रत्येक अपने फायदे और नुकसान के साथ, और अक्सर एक दी हुई स्थिति को स्टार्टअप समय पर JVM को इंगित करके टाला जा सकता है। कृपया परिदृश्य पर विस्तार से बताएं।
थोरबजोरन रेव एंडरसन

3
jmap -histo: live <pid> stackoverflow.com/questions/6418089/…

5
यहां कचरा संग्रहण के लिए उपयोग करने का मामला है: मेरे पास 30GB ढेर के साथ एक सर्वर है, जिसमें से ~ 12GB आमतौर पर उपयोग किया जाता है (~ 5M ऑब्जेक्ट)। हर 5 मिनट में, सर्वर लगभग एक मिनट एक जटिल कार्य करता है जिसमें लगभग 35M अतिरिक्त ऑब्जेक्ट का उपयोग किया जाता है। एक पूर्ण जीसी को जटिल कार्य के दौरान प्रति घंटे दो बार ट्रिगर किया जाता है, और वीएम को 10 से 15 सेकंड के लिए जमा देता है। मुझे पूर्ण जीसी को उस समय चलाने के लिए मजबूर करना पसंद होगा जब जटिल कार्य नहीं चल रहा हो; यह तब 40M के बजाय 5M जीवित वस्तुओं की बाजीगरी करेगा।
स्टीव

3
@JustinEthier एक बहुत स्पष्ट मामला है जहां आप GC को बाध्य करना चाह सकते हैं, जो कि java.lang.ref.Reference प्रकार के पदानुक्रम को शामिल करते हुए किसी भी व्यवहार का परीक्षण कर रहा है।
एलियास वासिलेंको

जवाबों:


168

आपका सबसे अच्छा विकल्प कॉल करना है System.gc()जो बस कचरा कलेक्टर को संकेत देता है कि आप इसे एक संग्रह करना चाहते हैं। बल और तत्काल संग्रह का कोई तरीका नहीं है, क्योंकि कचरा कलेक्टर गैर-नियतात्मक है।


28
होना चाहिये। non-deterministic == trouble
पचेरियर

7
एक कचरा संग्राहक गैर-निर्धारक हो सकता है और फिर भी तत्काल संग्रह को मजबूर करने का एक तरीका प्रदान करता है। उदाहरण के लिए, आमतौर पर .NET कलेक्टर गैर-नियतात्मक होता है, लेकिन GC.Collect () के लिए एक कॉल इसे चलाने के लिए मजबूर करता है। यह सिर्फ इतना है कि जावा इस फ़ंक्शन को उजागर नहीं करने का विकल्प चुनता है।
पेट्र हूडेक

2
मेरे अनुभव में, यह विधि हमेशा कचरा संग्रहकर्ता को आमंत्रित करती है। यह पर्याप्त नियमितता के साथ ऐसा करता है कि स्मृति के मेरे भूखंडों की संख्या बनाम घोषित वस्तुओं की संख्या हमेशा कड़ाई से रैखिक होती है (गद्दी के लिए लेखांकन, आदि)।
जिम पिवार्स्की

मैं सोच रहा था कि नई वस्तुओं को आवंटित करने और फिर उन्हें संदर्भित नहीं करने से, कचरा कलेक्टर स्वचालित रूप से चलेगा
Bionix1441

@ पेट्रूडेयेक वास्तविक दुनिया के एपेरियन नेट में GC.Collect()जमा नहीं होता है। जावा में gc()करता है।
अंजीह

53

Jlibs पुस्तकालय कचरा संग्रहण के लिए एक अच्छा उपयोगिता वर्ग है । आप WeakReference ऑब्जेक्ट्स के साथ एक निफ्टी छोटी चाल का उपयोग करके कचरा संग्रह को मजबूर कर सकते हैं।

जूलिब से RuntimeUtil.gc () :

   /**
    * This method guarantees that garbage collection is
    * done unlike <code>{@link System#gc()}</code>
    */
   public static void gc() {
     Object obj = new Object();
     WeakReference ref = new WeakReference<Object>(obj);
     obj = null;
     while(ref.get() != null) {
       System.gc();
     }
   }

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

1
आप "मेमोरी चला गया है" के साथ "जीसी चला गया है" का अर्थ भ्रमित हो सकता है। ऑब्जेक्ट पर रहता है और अभी तक अंतिम रूप नहीं दिया गया है, लेकिन आप इसे कमजोर संदर्भ के माध्यम से अब तक एक्सेस नहीं कर सकते हैं। एक बेहतर तरीका यह होगा कि आप इसके PhantomReferenceसाथ उपयोग करें ReferenceQueueऔर फिर आपको अंतिम रूप देने के बाद सूचित किया जाएगा, लेकिन फिर भी सफाई से पहले। अंत में, भले ही आपको सफलतापूर्वक पता चला हो कि इस ऑब्जेक्ट के लिए मेमोरी को पुनः प्राप्त किया गया था, फिर भी इसका मतलब हॉटस्पा जैसे जेनेरिक जीसी में बहुत कम होगा। आमतौर पर यह युवा पीढ़ी की सफाई के साथ मेल खाता था।
मार्को टोपोलनिक

20
ओपी ने अनुरोध किया, और आपने "कचरा संग्रह को मजबूर करने" के लिए एक समाधान प्रदान करने का दावा किया। जीसी सबसिस्टम चलाना एक बात है, वास्तव में कचरा इकट्ठा करना। आपके द्वारा प्रदान किया गया कोड नमूना स्पष्ट रूप से कचरा की गारंटी देने के इरादे से एकत्र किया गया है। वैसे भी, यह एक बहुत पुराना सवाल है, यह स्पष्ट रूप से ओपी की इच्छाओं के बारे में नहीं है, लेकिन आम जनता के लिए उपयोगिता है। किसी को भी "जीसी सबसिस्टम को चलाने के लिए मजबूर करने" में कोई दिलचस्पी नहीं है, जिसमें कोई कचरा एकत्र नहीं किया गया है। वास्तव में, लोग आमतौर पर एक गारंटी चाहते हैं कि सभी कचरा एकत्र किया गया है।
मार्को टोपोलनिक

4
आपने शायद इसकी तुलना दक्षता के साथ नहीं की थी System.gc(); System.gc();, लेकिन यह जानना दिलचस्प होगा कि क्या कभी इससे बेहतर काम हुआ। वास्तव में, सिर्फ यह छपाई करना कि यह कितनी बार System.gc()पर्याप्त होगा। कभी 2 तक पहुंचने का मौका काफी पतला है।
मार्को टोपोलनिक

3
@MarkoTopolnik: 'कोई भी अपने आप में जीसी सबसिस्टम को चलाने के लिए मजबूर करने में दिलचस्पी नहीं रखता है, जिसके पास कोई कचरा एकत्र नहीं होता है' .... वास्तव में आज सिर्फ इस व्यवहार में मेरी दिलचस्पी थी। मैं आभारी हूं कि यह जवाब मौजूद था। मेरा उद्देश्य जीसी लॉग हैंडलिंग के घूर्णी व्यवहार की जांच कर रहा था, और जीसी आउटपुट का प्रारूप प्राप्त कर रहा था। इस छोटी सी चाल ने मुझे जल्दी से जीसी लॉग भरने में मदद की।
erik.weathers 19

49

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

नोट: यह एक आसान जवाब नहीं है।


40
लुलज़ के लिए +1। कुछ भी नहीं निराशा निराशा की भावना के साथ किसी से बेहतर बनाता है। वास्तव में प्रयोग करने योग्य उत्तर के अलावा, वह है।
jsh

40

जावा ™ वर्चुअल मशीन टूल इंटरफेस (JVM TI) का उपयोग करके , फ़ंक्शन

jvmtiError ForceGarbageCollection(jvmtiEnv* env)

"कचरा संग्रह करने के लिए VM को बाध्य करेगा।" जेवीएम टीआई जावाटीएम प्लेटफॉर्म डिबगर आर्किटेक्चर (जेपीडीए) का हिस्सा है


25

हाँ, यह लगभग संभव है कि आपको उसी क्रम में विधियों पर कॉल करना होगा और उसी समय ये हैं:

System.gc ();
System.runFinalization ();

भले ही एक ही समय में इस दो विधियों के उपयोग को साफ करने के लिए केवल एक वस्तु हो, कचरा संग्रहकर्ता को finalise()सौंपी गई स्मृति को मुक्त करने और क्या करने की finalize()विधि करने के लिए अप्राप्य वस्तु की विधि का उपयोग करने के लिए मजबूर करना है।

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

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


10
नहीं , यहां तक ​​कि ये दो आदेश भी कचरा संग्रहण के लिए बाध्य नहीं करेंगे। जैसा कि पहले ही दूसरों ने उल्लेख किया है, gc()केवल एक कचरा संग्रह चलाने का संकेत है। runFinalizers()केवल उन वस्तुओं पर अंतिम रूप से चलता है "जिन्हें त्याग दिया गया है"। अगर जीसी वास्तव में नहीं चलती थी, तो ऐसी कोई वस्तु नहीं हो सकती ...
स्टीफन हील

भी, System.runFinalization () गारंटी नहीं है कि कुछ भी चलेगा; यह संभव है कि कुछ भी नहीं होगा। यह एक सुझाव है - जावदोक से: " इस पद्धति को कॉल करने से पता चलता है कि जावा वर्चुअल मशीन व्यय वस्तुओं के अंतिम तरीकों को चलाने की दिशा में प्रयास करती है, जिन्हें त्याग दिया गया है, लेकिन जिनके अंतिम तरीकों को अभी तक नहीं चलाया गया है "
kaan

21

OutOfMemoryError के लिए प्रलेखन के तहत यह घोषणा करता है कि इसे तब तक नहीं फेंका जाएगा जब तक कि वीएम एक पूर्ण कचरा संग्रह के बाद मेमोरी को पुनः प्राप्त करने में विफल नहीं हो जाता। इसलिए यदि आप त्रुटि प्राप्त होने तक मेमोरी आवंटित करते रहते हैं, तो आप पहले से ही एक पूर्ण कचरा संग्रह को मजबूर कर देंगे।

संभवत: वह प्रश्न जो आप वास्तव में पूछना चाहते थे, "मैं उस मेमोरी को कैसे पुनः प्राप्त कर सकता हूं जो मुझे लगता है कि मुझे कचरा संग्रह द्वारा पुनः प्राप्त करना चाहिए?"


18

GC से मैन्युअल रूप से अनुरोध करने के लिए (System.gc () से नहीं):

  1. इस पर जाएं: JDK में बिन फ़ोल्डर जैसे।-C: \ Program Files \ Java \ jdk1.6.0_31/ बिन
  2. Jconsole.exe खोलें
  3. वांछित स्थानीय प्रक्रिया से कनेक्ट करें।
  4. मेमोरी टैब पर जाएं और GC परफॉर्म करें पर क्लिक करें।

3
भ्रामक विरोध। कृपया माउस "जीसी प्रदर्शन करें" बटन पर चढ़ें। आप जेवीएम से जीसी प्रदर्शन करने का अनुरोध कर सकते हैं लेकिन कभी मजबूर नहीं।
कुमारन

@PinkeshSharma, यह बाध्य नहीं करता है । यह एक मात्र अनुरोध है जिसे शायद पूरी तरह से नजरअंदाज किया जा सकता है।
पचेरियर

@Pacerier एक आदर्श दुनिया में हाँ .. लेकिन अगर आप ऐसा करते हैं तो आप देखेंगे कि तुरंत याददाश्त में वृद्धि होती है ...
Pinkesh Sharma

11

.gc भविष्य के रिलीज में उन्मूलन के लिए एक उम्मीदवार है - एक सन इंजीनियर ने एक बार टिप्पणी की थी कि शायद दुनिया में बीस से भी कम लोग वास्तव में उपयोग करना जानते हैं ।gc () - मैंने कल रात कुछ काम कुछ घंटों के लिए केंद्रीय / महत्वपूर्ण पर किया था। सिक्योर-रेंडम जेनरेट किए गए डेटा का उपयोग करके डेटा-स्ट्रक्चर, कहीं-कहीं पिछले 40,000 ऑब्जेक्ट्स से vm धीमा हो जाएगा, क्योंकि यह पॉइंटर्स से बाहर चला गया था। स्पष्ट रूप से यह 16-बिट पॉइंटर टेबल पर घुट रहा था और क्लासिक "फेलिंग मशीनरी" व्यवहार को प्रदर्शित करता था।

मैंने कोशिश की -Xms और इतने पर, जब तक यह लगभग 57, xxx कुछ करने के लिए चलेगा, तब तक थोड़ा चक्कर लगाया। तब यह जीसी () (-) कैम्प ईज़ी मनी में कोड-ब्लोट की गति के बारे में ५,,१२ 57 से ५,,१२c कहने के लिए चल रहा होगा।

आपके डिजाइन को मौलिक पुन: काम करने की आवश्यकता है, शायद एक स्लाइडिंग विंडो दृष्टिकोण।


1
मेरे पास ऐसा कुछ है, स्मृति में बहुत सारी वस्तुएं जो मैं उन्हें नहीं दे सकता। OutOfMemory अपवाद को फेंक दिया गया है, मैं जांच करना चाहता हूं कि यदि कोई अनंत वस्तु निर्माण प्रक्रिया है, तो जीसी परीक्षण करना चाहता है या ये वस्तुएं मेरे सिस्टम द्वारा उपयोग की गई हैं।

लगता है कि आप उसी समस्या पर काम कर रहे हैं जो मैं हूं, pls समझाएं: "अनंत वस्तु निर्माण" ... अच्छा अनुसंधान परियोजना, शायद आप यहां एक जावा क्षेत्र में एक प्रश्न या कुछ पोस्ट कर सकते हैं (मैं यहां नया हूं और नहीं पता है कि "साइट कैसे काम करती है" का "ऑटोमैटिक ऑटोमैटिक" मैं कल कोशिश करता था और फाइल खत्म कर देता था। कंपाइलर ने 40,000 बेस 36 बिगबाइटर्स पर "बहुत ज्यादा कोड" शिकायत की थी, जिसे स्टैटिक फाइनल स्ट्रिंग के रूप में कोडित किया गया था [] मैं अपनी गर्दन चुरा रहा हूं। यहाँ और अनुमान लगाते हैं कि पूरी JVM 16-बिट पॉइंटर्स पर सीमित है, मुझे यकीन है कि हमें जो करना है वह एग्रेसिव रूप से अशक्त है और डिस्क से पढ़ा जाता है ...
निकोलस जॉर्डन

वास्तव में, मैं तुम्हें नहीं मिलता। लेकिन "अनंत वस्तु निर्माण" के बारे में स्पष्ट होने के लिए मेरा मतलब था कि मेरे बड़े सिस्टम में कोड का कुछ टुकड़ा है जो उन वस्तुओं का निर्माण करते हैं जिन्हें संभालता है और स्मृति में जीवित रहता है, मुझे वास्तव में केवल इशारे से कोड का यह टुकड़ा नहीं मिल सकता है !!

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

11

आप कमांड लाइन से GC को ट्रिगर कर सकते हैं। यह बैच / कोंट्राब के लिए उपयोगी है:

jdk1.7.0/bin/jcmd <pid> GC.run

देख :


1
संदर्भों के बारे में कुछ स्पष्टीकरण, टिप्पणियां या विवरण जोड़ने की कोशिश करें
10

6

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

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


4

यदि आपको कचरा संग्रहण के लिए मजबूर करने की आवश्यकता है, तो शायद आपको यह विचार करना चाहिए कि आप संसाधनों का प्रबंधन कैसे कर रहे हैं। क्या आप बड़ी वस्तुओं का निर्माण कर रहे हैं जो स्मृति में बनी रहती हैं? क्या आप बड़े ऑब्जेक्ट्स (उदाहरण के लिए, ग्राफिक्स क्लासेस) बना रहे हैं, जिनके पास Disposableइंटरफ़ेस है और dispose()जब इसके साथ कॉल नहीं किया जाता है? क्या आप एक वर्ग स्तर पर कुछ घोषित कर रहे हैं जो आपको केवल एक विधि के भीतर चाहिए?


2

यह बेहतर होगा यदि आप इस कारण का वर्णन करेंगे कि आपको कचरा संग्रहण की आवश्यकता क्यों है। यदि आप SWT का उपयोग कर रहे हैं, तो आप संसाधनों का निपटान कर सकते हैं जैसे कि Imageऔर Fontमेमोरी को मुक्त करना। उदाहरण के लिए:

Image img = new Image(Display.getDefault(), 16, 16);
img.dispose();

अपरिहार्य संसाधनों को निर्धारित करने के लिए उपकरण भी हैं।


क्या होगा यदि कोई निपटान विधि नहीं है?
आरिफमुस्तफा

1
सवाल से पूरी तरह से असंबंधित! नहीं, मैं SWT का उपयोग नहीं कर रहा हूं। मैं एक जेएनआई विधि कह रहा हूं जो डेल्फी देशी परत के माध्यम से एक .NET विंडो खोलता है। मेरे पास एक FORTRAN अभिकलन कोर है जो एक देशी C ++ परत के माध्यम से डेटा प्राप्त करता है। आपको इससे क्या करना है? मैं एक जीसी को मजबूर कर सकता हूं या नहीं? नहीं? :-(
मुस्तफा ज़िनाली

0

यदि आप स्मृति से बाहर चल रहे हैं और आप प्राप्त कर रहे हैं, तो आप OutOfMemoryExceptionके java -Xms128m -Xmx512mबजाय कार्यक्रम शुरू करने से जावा को उपलब्ध ढेर जगह की मात्रा बढ़ाने की कोशिश कर सकते हैं java। यह आपको 128Mb का शुरुआती आकार और अधिकतम 512Mb देगा, जो कि मानक 32Mb / 128Mb से कहीं अधिक है।


डिफ़ॉल्ट मेमोरी सेटिंग्स हैंjava -Xms512M -Xmx1024M
ThePyroEagle

0

एक और विकल्प नई वस्तुओं का निर्माण नहीं करना है।

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

ऑब्जेक्ट पूलिंग आमतौर पर ऑब्जेक्ट क्रिएशन (लाइट ऑब्जेक्ट्स के लिए एस्प) से अधिक तेज नहीं होने वाला है, लेकिन यह गारबेज कलेक्शन से तेज है। यदि आपने 10,000 ऑब्जेक्ट्स बनाए हैं और प्रत्येक ऑब्जेक्ट 16 बाइट्स था। कि 160,000 बाइट्स GC को पुनः प्राप्त करना है। दूसरी ओर, यदि आपको एक ही समय में सभी 10,000 की आवश्यकता नहीं है, तो आप ऑब्जेक्ट्स को रीसायकल / पुन: उपयोग करने के लिए एक पूल बना सकते हैं जो नई वस्तुओं के निर्माण की आवश्यकता को समाप्त करता है और जीसी पुरानी वस्तुओं की आवश्यकता को समाप्त करता है।

कुछ इस तरह (अप्रकाशित)। और यदि आप चाहते हैं कि यह थ्रेड सुरक्षित हो तो आप LinkedList को एक समवर्ती Linkedue के लिए स्वैप कर सकते हैं।

public abstract class Pool<T> {
    private int mApproximateSize;
    private LinkedList<T> mPool = new LinkedList<>();

    public Pool(int approximateSize) {
        mApproximateSize = approximateSize;
    }

    public T attain() {
        T item = mPool.poll();
        if (item == null) {
            item = newInstance();
        }
        return item;
    }

    public void release(T item) {
        int approxSize = mPool.size(); // not guaranteed accurate
        if (approxSize < mApproximateSize) {
            recycle(item);
            mPool.add(item);
        } else if (approxSize > mApproximateSize) {
            decommission(mPool.poll());
        }
    }

    public abstract T newInstance();

    public abstract void recycle(T item);

    public void decommission(T item) { }

}

0

G1 GC के साथ OracleJDK 10 पर, एकल System.gc()संग्रह से GC को पुराने संग्रह को साफ करने का कारण होगा। मुझे यकीन नहीं है कि जीसी तुरंत चलता है। हालाँकि, GC System.gc()किसी लूप में कई बार कॉल करने पर भी यंग कलेक्शन को क्लीन नहीं करेगा । युवा संग्रह को साफ करने के लिए जीसी प्राप्त करने के लिए, आपको new byte[1024]बिना कॉल किए एक लूप (जैसे ) में आवंटित करना होगा System.gc()System.gc()किसी कारण से कॉल करना GC को यंग कलेक्शन को साफ करने से रोकता है।


0

वास्तव में, मैं तुम्हें नहीं मिलता। लेकिन "अनंत वस्तु निर्माण" के बारे में स्पष्ट होने के लिए मेरा मतलब था कि मेरे बड़े सिस्टम में कोड का कुछ टुकड़ा है जो उन वस्तुओं का निर्माण करते हैं जिन्हें संभालता है और स्मृति में जीवित रहता है, मुझे वास्तव में केवल इशारे से कोड का यह टुकड़ा नहीं मिल सकता है !!

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

  1. मुझे वास्तव में कोड का यह टुकड़ा नहीं मिला

सही है, कोई वास्तविक jvm नहीं है - ऐसा केवल एक विनिर्देश है, कंप्यूटर विज्ञान का एक गुच्छा जो एक वांछित व्यवहार का वर्णन करता है ... मैंने हाल ही में मूल कोड से जावा ऑब्जेक्ट को आरंभीकृत करने में खोदा था। आप जो चाहते हैं उसे पाने के लिए, एकमात्र तरीका यह है कि आक्रामक अशक्तता कहा जाए। गलतियाँ करने पर गलतियाँ इतनी बुरी होती हैं कि हमें खुद को सवाल के मूल दायरे तक सीमित रखना पड़ता है:

  1. मेरे बड़े सिस्टम में कोड का कुछ भाग वस्तुओं का निर्माण करता है

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

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

किसी भी समय आपको या मुझे या किसी और को मिलता है: " कृपया मुझे उस घबराहट की आवश्यकता है। " यह लगभग सार्वभौमिक अग्रदूत है कि आप जिस पर काम करने की कोशिश कर रहे हैं, उसके कुल विनाश के लिए .... हमें एक छोटा सा नमूना कोड लिखें, इसमें से किसी को भी संक्षिप्त करना। वास्तविक कोड का इस्तेमाल किया और हमें अपना सवाल दिखाया।

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

यह बहुत आम है।


-1

FYI करें

मेथड कॉल सिस्टम System.runFinalizersOnExit (सच) यह गारंटी देता है कि जावा शट डाउन करने से पहले अंतिम तरीके को कहा जाता है। हालाँकि, यह विधि स्वाभाविक रूप से असुरक्षित है और इसे हटा दिया गया है। एक विकल्प Runtime.addShutdownHook विधि के साथ "शटडाउन हुक" जोड़ने के लिए है।

मसर्रत सिद्दीकी


शटडाउन हुक के साथ दोष यह है कि वे शायद ही कभी काम करते हैं। फोर्स टर्मिनेटिंग काम नहीं करता है, गैर-शून्य एग्जिट कोड काम नहीं करता है, और कभी-कभी (आधिकारिक) जेवीएम उन्हें केवल तब तक नहीं चलाता है जब तक आपको उन्हें चलाने की आवश्यकता होती है।
thePyroEagle

-1

कचरा संग्रह करने के लिए कुछ अप्रत्यक्ष तरीका है। आपको बस तब तक अस्थायी वस्तुओं के साथ ढेर भरने की जरूरत है जब तक कि कचरा कलेक्टर निष्पादित नहीं होगा। मैंने वर्ग बनाया है जो इस तरह से कचरा इकट्ठा करने वालों को मजबूर करता है:

class GarbageCollectorManager {

    private static boolean collectionWasForced;
    private static int refCounter = 0;

    public GarbageCollectorManager() {
        refCounter++;
    }

    @Override
    protected void finalize() {
        try {
            collectionWasForced = true;
            refCounter--;
            super.finalize();   
        } catch (Throwable ex) {
            Logger.getLogger(GarbageCollectorManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public int forceGarbageCollection() {
        final int TEMPORARY_ARRAY_SIZE_FOR_GC = 200_000;
        int iterationsUntilCollected = 0;
        collectionWasForced = false;

        if (refCounter < 2) 
            new GarbageCollectorManager();

        while (!collectionWasForced) {
            iterationsUntilCollected++;
            int[] arr = new int[TEMPORARY_ARRAY_SIZE_FOR_GC];
            arr = null;
        }

        return iterationsUntilCollected;
    }

}

उपयोग:

GarbageCollectorManager manager = new GarbageCollectorManager();
int iterationsUntilGcExecuted = manager.forceGarbageCollection();

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


"अंतिम int TEMPORARY_ARRAY_SIZE_FOR_GC = 200_000 क्या है?"
कोरे तुगे

सरणी का आकार - जीसी के लिए काम करना शुरू करने के लिए कितने अस्थायी ऑब्जेक्ट (इंट) उत्पन्न होंगे।
अग्निस वसीलियास्कस

क्या यह पूर्णांक: "_" पूर्णांक में है?
कोरे तुगे

1
हां, अंकीय शाब्दिक में अंडरस्कोर जावा एसई 7 से शुरू होने वाले वैध हैं। यह उदाहरण के लिए इस मामले में पूर्णांक में हजारों विभाजक के रूप में उपयोगी है।
अग्निस वसीलियास्कस

3
आपको उत्पादन प्रणाली में कभी भी ऐसा कोड नहीं चलाना चाहिए । जबकि यह कोड एक धागे में चलता है, किसी भी अन्य धागे को एक आउटऑफ़मेरी एक्ससेप्शन भी मिल सकता है, इसे पूरी तरह से कॉल करने के इरादे से पहली जगह में ....
स्टीफन हील

-1

मैं यहां कुछ बात जोड़ना चाहूंगा। कृपया नहीं कि जावा वर्चुअल मशीन पर चलता है और वास्तविक मशीन पर नहीं। वर्चुअल मशीन का मशीन के साथ संचार का अपना तरीका है। यह सिस्टम से सिस्टम में भिन्न हो सकता है। अब जब हम GC को कॉल करते हैं तो हम जावा के वर्चुअल मशीन को कचरा संग्राहक कहते हैं।

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


दूसरे पैराग्राफ का पहला वाक्य एक गैर अनुक्रमिक है
को लोर्न के

-1

निम्नलिखित कोड assertGC (...) विधि से लिया गया है। यह nondeterministic कचरा कलेक्टर को इकट्ठा करने के लिए मजबूर करने की कोशिश करता है।

   List<byte[]> alloc = new ArrayList<byte[]>();
   int size = 100000;
   for (int i = 0; i < 50; i++) {
        if (ref.get() == null) {
             // Test succeeded! Week referenced object has been cleared by gc.
             return;
        }
        try {
             System.gc();
        } catch (OutOfMemoryError error) {
             // OK
        }
        try {
             System.runFinalization();
        } catch (OutOfMemoryError error) {
             // OK
        }

        // Approach the jvm maximal allocatable memory threshold
        try {
             // Allocates memory.
             alloc.add(new byte[size]);

             // The amount of allocated memory is increased for the next iteration.
             size = (int)(((double)size) * 1.3);
        } catch (OutOfMemoryError error) {
             // The amount of allocated memory is decreased for the next iteration.
             size = size / 2;
        }

        try {
             if (i % 3 == 0) Thread.sleep(321);
        } catch (InterruptedException t) {
             // ignore
        }
   }

   // Test failed! 

   // Free resources required for testing
   alloc = null;

   // Try to find out who holds the reference.
   String str = null;
   try {
        str = findRefsFromRoot(ref.get(), rootsHint);
   } catch (Exception e) {
        throw new AssertionFailedErrorException(e);
   } catch (OutOfMemoryError err) {
        // OK
   }
   fail(text + ":\n" + str);

स्रोत (मैंने स्पष्टता के लिए कुछ टिप्पणियाँ जोड़ी): NbTestCase उदाहरण


-1

आप Runtime.getRuntime().gc()उपयोगिता विधि का उपयोग या उपयोग करने का प्रयास कर सकते हैं System.gc()नोट: ये विधियाँ GC को सुनिश्चित नहीं करती हैं। और उनका दायरा आपके आवेदन में प्रोग्रामेटिक रूप से संभालने के बजाय जेवीएम तक सीमित होना चाहिए।


2
जैसा कि अन्य उत्तरों में बताया गया है, वे विधियाँ एक (पूर्ण) कचरा संग्रह चलाने के लिए बाध्य नहीं करती हैं।
फ्लो

-2

यदि आप JUnit और स्प्रिंग का उपयोग कर रहे हैं, तो इसे हर परीक्षण वर्ग में जोड़ने का प्रयास करें:

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