java - मेमोरी फाइल डाउनलोड




एक स्ट्रिंग सहेजने मेमोरी को "" क्यों जोड़ रहा है? (6)

String data कहें, मैंने इसमें बहुत सारे डेटा के साथ एक चर का उपयोग किया था। मैं इस स्ट्रिंग के एक छोटे से हिस्से को निम्न तरीके से उपयोग करना चाहता था:

this.smallpart = data.substring(12,18);

कुछ घंटों के डिबगिंग (मेमोरी विज़ुअलाइज़र के साथ) के बाद मुझे पता चला कि ऑब्जेक्ट फ़ील्ड smallpart से data को डेटा से सभी डेटा याद आया, हालांकि इसमें केवल सबस्ट्रिंग शामिल था।

जब मैंने कोड को बदल दिया:

this.smallpart = data.substring(12,18)+""; 

..समस्या का निदान हो गया था! अब मेरा आवेदन बहुत कम स्मृति का उपयोग करता है!

वो कैसे संभव है? क्या कोई इसे समझा सकता है? मुझे लगता है कि इस.smallpart डेटा की ओर संदर्भित रखा, लेकिन क्यों?

अद्यतन: मैं तब बड़ी स्ट्रिंग को कैसे साफ़ कर सकता हूं? क्या डेटा = नया स्ट्रिंग (data.substring (0,100)) चीज़ करेगा?


मुझे लगता है कि इस.smallpart डेटा की ओर संदर्भित रखा, लेकिन क्यों?

चूंकि जावा स्ट्रिंग्स में चार सरणी होती है, एक स्टार्ट ऑफसेट और लम्बाई (और एक कैश हैशकोड)। कुछ स्ट्रिंग ऑपरेशंस जैसे substring() एक नई स्ट्रिंग ऑब्जेक्ट बनाते हैं जो मूल के चार सरणी को साझा करता है और इसमें अलग ऑफसेट और / या लम्बाई फ़ील्ड होता है। यह काम करता है क्योंकि स्ट्रिंग की चार सरणी इसे बनाए जाने के बाद कभी संशोधित नहीं होती है।

यह स्मृति को सहेज सकता है जब कई सबस्ट्रिंग ओवरलैपिंग भागों को दोहराने के बिना समान मूल स्ट्रिंग को संदर्भित करते हैं। जैसा कि आपने देखा है, कुछ परिस्थितियों में, यह उस डेटा को रख सकता है जिसे कचरा होने से अब और आवश्यकता नहीं है।

इसे ठीक करने का "सही" तरीका new String(String) कन्स्ट्रक्टर है, यानी

this.smallpart = new String(data.substring(12,18));

बीटीडब्लू, कुल मिलाकर सबसे अच्छा समाधान पहली जगह में बहुत बड़े स्ट्रिंग्स से बचने और छोटे हिस्सों में किसी भी इनपुट को प्रोसेस करने से बचाना होगा, एक समय में कुछ केबी।


एक स्ट्रिंग में "" संलग्न करना कभी-कभी स्मृति को बचाएगा।

मान लीजिए कि मेरे पास एक बड़ी स्ट्रिंग है जिसमें एक पूरी किताब, दस लाख वर्ण हैं।

फिर मैं पुस्तक के अध्यायों को सब्सट्रिंग के रूप में 20 तार बना देता हूं।

फिर मैं सभी अनुच्छेदों सहित 1000 तार बना देता हूं।

फिर मैं सभी वाक्यों वाले 10,000 तार बना देता हूं।

फिर मैं 100,000 स्ट्रिंग्स बना देता हूं जिसमें सभी शब्द होते हैं।

मैं अभी भी केवल 1,000,000 वर्णों का उपयोग करता हूं। यदि आप प्रत्येक अध्याय, अनुच्छेद, वाक्य और शब्द में "" जोड़ते हैं, तो आप 5,000,000 वर्णों का उपयोग करते हैं।

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

और यदि आपके पास एक मिलियन वर्ण स्ट्रिंग है और दोनों सिरों पर टैब और रिक्त स्थान हटाएं तो यह फिर से अलग है, एक सबस्ट्रिंग बनाने के लिए 10 कॉल कहें। जिस तरह से जावा काम करता है या काम करता है, हर बार दस लाख वर्णों की प्रतिलिपि बनाने से बचाता है। समझौता है, और यह अच्छा है अगर आप जानते हैं कि समझौता क्या है।


जावा स्ट्रिंग्स में इमेटेबल ऑब्जेक्ट्स हैं और स्ट्रिंग बनने के बाद, यह कचरा कलेक्टर द्वारा साफ किए जाने तक स्मृति पर बना रहता है (और यह सफाई ऐसी चीज नहीं है जिसे आप मंजूरी दे सकते हैं)।

जब आप सबस्ट्रिंग विधि को कॉल करते हैं, तो जावा एक ट्रूली नई स्ट्रिंग नहीं बनाता है, लेकिन मूल स्ट्रिंग के अंदर केवल वर्णों की एक श्रृंखला संग्रहीत करता है।

इसलिए, जब आपने इस कोड के साथ एक नई स्ट्रिंग बनाई:

this.smallpart = data.substring(12, 18) + ""; 

जब आप खाली स्ट्रिंग के साथ परिणाम को जोड़ते हैं तो आपने वास्तव में एक नई स्ट्रिंग बनाई है। इसीलिए।


जैसा कि 1 99 7 में जेडब्ल्यूजे द्वारा दस्तावेज किया गया था :

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


बस संक्षेप में, यदि आप बड़ी संख्या में बड़े तारों से बहुत सारे सबस्ट्रिंग बनाते हैं, तो इसका उपयोग करें

   String subtring = string.substring(5,23)

चूंकि आप बड़े स्ट्रिंग्स को स्टोर करने के लिए केवल स्पेस का उपयोग करते हैं, लेकिन यदि आप बड़े स्ट्रिंग्स के खोने से छोटे टुकड़ों को थोड़ा सा निकाल रहे हैं, तो

   String substring = new String(string.substring(5,23));

आपकी याददाश्त का उपयोग कम रहेगा, क्योंकि अब जब आवश्यक हो तो बड़े तारों को पुनः दावा किया जा सकता है।

जिसे आप new String कहते हैं, एक सहायक अनुस्मारक है कि आपको वास्तव में मूल संदर्भ के बजाय एक नई स्ट्रिंग मिल रही है।


यदि आप substring(int, int) के स्रोत को देखते हैं, तो आप देखेंगे कि यह लौटाता है:

new String(offset + beginIndex, endIndex - beginIndex, value);

जहां मूल मूल char[] । तो आपको एक नया स्ट्रिंग मिलता है लेकिन उसी अंतर्निहित char[]

जब आप करते हैं, data.substring() + "" , आपको एक नया अंतर्निहित char[] data.substring() + "" साथ एक नया स्ट्रिंग मिलता है।

असल में, आपका उपयोग केस एकमात्र ऐसी स्थिति है जहां आपको String(String) कन्स्ट्रक्टर का उपयोग करना चाहिए:

String tiny = new String(huge.substring(12,18));




memory