क्या जावा में मुफ्त मेमोरी का एक तरीका है, सी के free()
फ़ंक्शन के समान है ? या जीसी पर एकमात्र विकल्प को शून्य और निर्भर करने के लिए ऑब्जेक्ट सेट कर रहा है?
क्या जावा में मुफ्त मेमोरी का एक तरीका है, सी के free()
फ़ंक्शन के समान है ? या जीसी पर एकमात्र विकल्प को शून्य और निर्भर करने के लिए ऑब्जेक्ट सेट कर रहा है?
जवाबों:
जावा प्रबंधित मेमोरी का उपयोग करता है, इसलिए new
ऑपरेटर द्वारा उपयोग करके मेमोरी को आवंटित करने का एकमात्र तरीका है , और कचरा कलेक्टर पर भरोसा करने का एकमात्र तरीका यह है कि आप मेमोरी को हटा सकते हैं।
यह स्मृति प्रबंधन व्हाइटपेपर (PDF) यह बताने में मदद कर सकता है कि क्या हो रहा है।
आप यह System.gc()
सुझाव देने के लिए भी कॉल कर सकते हैं कि कचरा संग्रहकर्ता तुरंत चलता है। हालाँकि, जावा रनटाइम अंतिम निर्णय लेता है, न कि आपका कोड।
जावा प्रलेखन के अनुसार ,
जीसी विधि को कॉल करने से पता चलता है कि जावा वर्चुअल मशीन खर्च की गई वस्तुओं को पुन: उपयोग करने के लिए अप्रयुक्त वस्तुओं को पुन: उपयोग करने की दिशा में खर्च करती है, जो कि वे वर्तमान में त्वरित पुन: उपयोग के लिए उपलब्ध हैं। जब विधि कॉल से नियंत्रण लौटाता है, तो जावा वर्चुअल मशीन ने सभी छोड़ी गई वस्तुओं से अंतरिक्ष को पुनः प्राप्त करने का एक अच्छा प्रयास किया है।
System.gc()
पूरी तरह से अनदेखा करते हैं ।
ऐसा प्रतीत नहीं होता है कि किसी ने स्पष्ट रूप से ऑब्जेक्ट रेफ़रेंस का उल्लेख किया है null
, जो कि आप जिस "स्मृति" पर विचार करना चाहते हैं उसे "मुक्त" करने की एक वैध तकनीक है।
उदाहरण के लिए, मान लें कि आपने List<String>
एक विधि की शुरुआत में घोषणा की थी जो आकार में बहुत बड़ी हो गई थी, लेकिन केवल विधि के माध्यम से आधे रास्ते तक आवश्यक थी। आप इस बिंदु पर सूची संदर्भ सेट कर सकते हैं null
कि विधि को पूरा करने से पहले कचरा कलेक्टर को संभावित रूप से इस वस्तु को पुनः प्राप्त करने की अनुमति दें (और संदर्भ वैसे भी दायरे से बाहर हो जाता है)।
ध्यान दें कि मैं शायद ही कभी इस तकनीक का वास्तविकता में उपयोग करता हूं लेकिन यह बहुत बड़े डेटा संरचनाओं से निपटने पर विचार करने योग्य है।
System.gc();
कूड़ा बीनने वाला चलाता है।
जीसी विधि को कॉल करने से पता चलता है कि जावा वर्चुअल मशीन व्यय की गई पुन: उपयोग के लिए उपलब्ध वस्तुओं को पुन: उपयोग करने के लिए अप्रयुक्त वस्तुओं को पुन: उपयोग करने की दिशा में प्रयास करती है। जब विधि कॉल से नियंत्रण लौटाता है, तो जावा वर्चुअल मशीन ने सभी छोड़ी गई वस्तुओं से अंतरिक्ष को पुनः प्राप्त करने का एक अच्छा प्रयास किया है।
सिफारिश नहीं की गई।
संपादित करें: मैंने 2009 में मूल प्रतिक्रिया लिखी थी। अब यह 2015 है।
कचरा संग्रहकर्ताओं ने जावा के आसपास के ~ 20 वर्षों में लगातार बेहतर प्रदर्शन किया है। इस बिंदु पर, यदि आप मैन्युअल रूप से कचरा संग्रहकर्ता को बुला रहे हैं, तो आप अन्य दृष्टिकोणों पर विचार करना चाह सकते हैं:
* "मैं व्यक्तिगत रूप से भविष्य के उचित विलोपन के लिए प्लेसहोल्डर के रूप में चर को हटाने पर भरोसा करता हूं। उदाहरण के लिए, मैं सरणी के सभी तत्वों को वास्तव में हटाने से पहले एक सरणी के सभी तत्वों को अशक्त करने के लिए समय लेता हूं।"
यह अनावश्यक है। जिस तरह से जावा जीसी काम करता है वह ऐसी वस्तुओं को ढूंढता है जिनका कोई संदर्भ नहीं है, इसलिए यदि मेरे पास ऑब्जेक्ट x (संदर्भ = चर) है जो इसे इंगित करता है, तो जीसी इसे हटा नहीं देगा, क्योंकि एक संदर्भ है उस वस्तु के लिए:
a -> x
यदि आप ऐसा होने की तुलना में शून्य करते हैं:
a -> null
x
तो अब x के पास इसे इंगित करने वाला संदर्भ नहीं है और इसे हटा दिया जाएगा। जब आप x से भिन्न ऑब्जेक्ट के संदर्भ में सेट करते हैं तो वही बात होती है।
इसलिए यदि आपके पास एक एरे गिरफ्तार है जो ऑब्जेक्ट x, y और z के संदर्भ में है और एक चर है जो एरे के संदर्भ में है जो ऐसा दिखता है:
a -> arr -> x
-> y
-> z
यदि आप ऐसा होने की तुलना में शून्य करते हैं:
a -> null
arr -> x
-> y
-> z
इसलिए जीसी को गिरफ्तार किया जाता है क्योंकि इसका कोई संदर्भ नहीं है और इसे हटा दिया जाता है, जो आपको यह संरचना प्रदान करता है:
a -> null
x
y
z
अब GC x, y और z को ढूँढता है और उन्हें हटा देता है। सरणी में प्रत्येक संदर्भ को खींचने से कुछ भी बेहतर नहीं होगा, यह कोड में सीपीयू समय और स्थान का उपयोग करेगा (यह कहा, यह उससे आगे चोट नहीं करेगा। जीसी अभी भी उस तरह से प्रदर्शन करने में सक्षम होगा। )।
किसी भी प्रोग्राम (जावा या नहीं) से मुक्त मेमोरी चाहने का एक वैध कारण ऑपरेटिंग सिस्टम स्तर पर अन्य प्रोग्रामों को अधिक मेमोरी उपलब्ध कराना है। अगर मेरा जावा एप्लिकेशन 250MB का उपयोग कर रहा है, तो मैं इसे 1MB तक नीचे करना और 249MB अन्य ऐप्स के लिए उपलब्ध कराना चाह सकता हूं।
Yiannis Xanthopoulos और Hot Licks द्वारा जवाब और टिप्पणी का विस्तार करने के लिए (क्षमा करें, मैं अभी तक टिप्पणी नहीं कर सकता!), आप इस उदाहरण की तरह वीएम विकल्प सेट कर सकते हैं:
-XX:+UseG1GC -XX:MinHeapFreeRatio=15 -XX:MaxHeapFreeRatio=30
मेरी jdk 7 में यह तब अप्रयुक्त वीएम मेमोरी जारी करेगा यदि 30% से अधिक ढेर जीसी के बाद मुक्त हो जाता है जब वीएम निष्क्रिय होता है। आपको शायद इन मापदंडों को ट्यून करने की आवश्यकता होगी।
जब मैंने इसे नीचे दिए गए लिंक में जोर नहीं दिया, तो ध्यान दें कि कुछ कचरा संग्रहकर्ता इन मापदंडों का पालन नहीं कर सकते हैं और डिफ़ॉल्ट रूप से जावा आपके लिए इनमें से एक चुन सकता है, तो क्या आपके पास एक से अधिक कोर होना चाहिए (इसलिए UseG1GC तर्क ऊपर है )।
अपडेट: जावा 1.8.0_73 के लिए मैंने जेवीएम को कभी-कभी डिफ़ॉल्ट सेटिंग्स के साथ छोटी मात्रा में जारी किया है। केवल यह करने के लिए प्रकट होता है अगर ~ 70% हीप अप्रयुक्त है, लेकिन यह नहीं पता है कि यदि ओएस भौतिक मेमोरी पर कम था, तो यह अधिक आक्रामक रिलीज़ होगा।
मैंने इस पर प्रयोग किया है।
यह सच है कि System.gc();
केवल कचरा कलेक्टर को चलाने का सुझाव है।
लेकिन System.gc();
सभी संदर्भों को निर्धारित करने के बाद कॉल करने से null
प्रदर्शन और मेमोरी व्यवसाय में सुधार होगा।
यदि आप वास्तव में आवंटित करना चाहते हैं और मेमोरी का एक ब्लॉक मुक्त करना चाहते हैं तो आप इसे सीधे बाइटफर्फ़र्स के साथ कर सकते हैं। मेमोरी को फ्री करने का एक गैर-पोर्टेबल तरीका भी है।
हालाँकि, जैसा कि सुझाव दिया गया है, सिर्फ इसलिए कि आपको सी में मेमोरी को खाली करना है, इसका मतलब यह नहीं है कि ऐसा करना एक अच्छा विचार है।
यदि आपको लगता है कि आपके पास वास्तव में मुफ्त के लिए एक अच्छा उपयोग मामला है (), तो कृपया इसे प्रश्न में शामिल करें ताकि हम देख सकें कि आप क्या करने जा रहे हैं, यह एक बेहतर तरीका है।
Javacfishbreak.com/faq/faq0012.html से पूरी तरह से
एक कम प्राथमिकता वाला धागा उपयोगकर्ता के लिए स्वचालित रूप से कचरा संग्रहण का ख्याल रखता है। निष्क्रिय समय के दौरान, थ्रेड को बुलाया जा सकता है, और यह जावा में किसी ऑब्जेक्ट को पहले से आवंटित मेमोरी को मुफ्त करना शुरू कर सकता है। लेकिन चिंता मत करो - यह आप पर अपनी वस्तुओं को नष्ट नहीं करेगा!
जब किसी वस्तु का कोई संदर्भ नहीं होता है, तो यह कचरा संग्राहक के लिए उचित खेल बन जाता है। कुछ रूटीन (जैसे सी ++ में मुफ्त) कॉल करने के बजाय, आप बस ऑब्जेक्ट के सभी संदर्भों को शून्य करने के लिए असाइन करते हैं, या संदर्भ के लिए एक नया वर्ग असाइन करते हैं।
उदाहरण :
public static void main(String args[]) { // Instantiate a large memory using class MyLargeMemoryUsingClass myClass = new MyLargeMemoryUsingClass(8192); // Do some work for ( .............. ) { // Do some processing on myClass } // Clear reference to myClass myClass = null; // Continue processing, safe in the knowledge // that the garbage collector will reclaim myClass }
यदि आपका कोड बड़ी मात्रा में मेमोरी का अनुरोध करने वाला है, तो आप चाहते हैं कि कचरा संग्रहकर्ता पुनः प्राप्त करना शुरू कर सके, बजाय इसके कि इसे कम प्राथमिकता वाले धागे के रूप में करने की अनुमति दी जाए। ऐसा करने के लिए, अपने कोड में निम्नलिखित जोड़ें
System.gc();
कचरा संग्राहक मुक्त स्थान को पुनः प्राप्त करने का प्रयास करेगा, और आपका आवेदन निष्पादित करना जारी रख सकता है, जितना संभव हो उतना मेमोरी पुनः प्राप्त किया जा सकता है (कुछ प्लेटफॉर्म पर स्मृति विखंडन के मुद्दे लागू हो सकते हैं)।
मेरे मामले में, चूंकि मेरा जावा कोड निकट भविष्य में अन्य भाषाओं (मुख्य रूप से C ++) में पोर्ट किया जाना है, इसलिए मैं कम से कम स्मृति को ठीक करने के लिए होंठ सेवा का भुगतान करना चाहता हूं ताकि यह बाद में पोर्टिंग प्रक्रिया में मदद करे।
मैं व्यक्तिगत रूप से भविष्य के उचित विलोपन के लिए एक प्लेसहोल्डर के रूप में चर को हटाने पर भरोसा करता हूं। उदाहरण के लिए, मैं किसी सरणी के सभी तत्वों को वास्तव में हटाने से पहले सरणी को हटाने (शून्य करने) के लिए समय लेता हूं।
लेकिन मेरा मामला बहुत खास है, और मुझे पता है कि मैं ऐसा करते समय प्रदर्शन हिट ले रहा हूं।
* "उदाहरण के लिए, मान लें कि आपने एक विधि की शुरुआत में एक सूची घोषित की है जो आकार में बहुत बड़ी हो गई है, लेकिन केवल विधि के माध्यम से आधे रास्ते तक आवश्यक थी। आप इस बिंदु पर सूची के संदर्भ को अशक्त करने के लिए निर्धारित कर सकते हैं। विधि के पूरा होने से पहले कचरा कलेक्टर को संभावित रूप से पुनः प्राप्त करने की अनुमति देने के लिए (और संदर्भ वैसे भी गुंजाइश से बाहर हो जाता है)। " *
यह सही है, लेकिन यह समाधान सामान्य नहीं हो सकता है। Null -will के लिए सूची ऑब्जेक्ट संदर्भ सेट करते समय- कचरा संग्रहण के लिए स्मृति उपलब्ध कराएं, यह केवल प्राथमिक प्रकारों की सूची ऑब्जेक्ट के लिए सही है। यदि सूची ऑब्जेक्ट के बजाय संदर्भ प्रकार समाहित करते हैं, तो सूची ऑब्जेक्ट सेट करना = null संदर्भ-प्रकार के निहित -any- को नहीं करेगा-सूची। इस स्थिति में, सूची ऑब्जेक्ट सेट करना = निहित संदर्भ प्रकारों को अनाथ कर देगा, जिनकी वस्तुएं कचरा संग्रहण के लिए उपलब्ध नहीं होंगी, जब तक कि कचरा संग्रह एल्गोरिदम यह निर्धारित करने के लिए पर्याप्त स्मार्ट नहीं है कि ऑब्जेक्ट अनाथ हो गए हैं।
अल्रिथ जावा स्वचालित कचरा संग्रह प्रदान करता है कभी-कभी आप जानना चाहेंगे कि वस्तु कितनी बड़ी है और यह कितनी शेष है। मुफ्त मेमोरी का उपयोग करके import java.lang;
और Runtime r=Runtime.getRuntime();
स्मृति के मूल्यों को प्राप्त करने के mem1=r.freeMemory();
लिए मुफ्त मेमोरी कॉल r.gc();
विधि और कॉल का उपयोग करें।freeMemory()
JAVA से सिफारिश करना है कि वह अशक्त हो जाए
से https://docs.oracle.com/cd/E19159-01/819-3681/abebi/index.html
स्पष्ट रूप से उन चरों को एक शून्य मान प्रदान करना जिनकी अब आवश्यकता नहीं है, कचरा संग्रहकर्ता को स्मृति के उन हिस्सों की पहचान करने में मदद करता है जिन्हें सुरक्षित रूप से पुनः प्राप्त किया जा सकता है। यद्यपि जावा मेमोरी प्रबंधन प्रदान करता है, यह मेमोरी लीक या अत्यधिक मात्रा में मेमोरी का उपयोग करने से नहीं रोकता है।
ऑब्जेक्ट संदर्भों को जारी न करके एक एप्लिकेशन मेमोरी लीक को प्रेरित कर सकता है। ऐसा करने से जावा कचरा संग्रहकर्ता को उन वस्तुओं को पुनः प्राप्त करने से रोकता है, और इसके परिणामस्वरूप स्मृति की बढ़ती मात्रा का उपयोग किया जाता है। स्पष्ट रूप से उनके उपयोग के बाद चर के संदर्भों को अशक्त करना कचरा कलेक्टर को स्मृति को पुनः प्राप्त करने की अनुमति देता है।
मेमोरी लीक का पता लगाने का एक तरीका है कि प्रोफाइलिंग टूल को नियोजित किया जाए और प्रत्येक लेनदेन के बाद मेमोरी स्नैपशॉट लें। स्थिर अवस्था में एक रिसाव-मुक्त अनुप्रयोग कचरा संग्रहण के बाद एक स्थिर सक्रिय ढेर मेमोरी दिखाएगा।