2013-01-04 12 views
14

मैं स्ट्रिंग क्लास एपीआई के माध्यम से जा रहा था और ऐसा लगता है कि सबस्ट्रिंग विधि के कारण संभावित मेमोरी रिसाव है क्योंकि यह मूल स्ट्रिंग के समान चरित्र सरणी साझा करता है।जावा स्ट्रिंग.substring विधि संभावित स्मृति रिसाव?

यदि मूल स्ट्रिंग बहुत बड़ी है तो सबस्ट्रिंग द्वारा लौटाई गई छोटी स्ट्रिंग जावा में कचरा संग्रह से मूल स्ट्रिंग (बड़े सरणी द्वारा समर्थित) को रोक सकती है।

कोई विचार या मैंने एपीआई गलत पढ़ा।

+2

यह तकनीकी रूप से एक स्मृति रिसाव नहीं है, क्योंकि चरित्र सरणी अभी भी संदर्भित है और इसे बाद में एकत्र किया जा सकता है जब सभी स्ट्रिंग्स जो इसे संदर्भित करते हैं। चरित्र सरणी का हिस्सा अब और उपयोग नहीं किया जा सकता है, लेकिन यह इसे रिसाव नहीं बनाता है। – cdhowie

+1

यदि आपके पास प्रत्येक 100 एमबी 100 बड़ी स्ट्रिंग है और आपके पास एक सबस्ट्रिंग (0,1) है तो आप तकनीकी रूप से उस मूल्य को पकड़ रहे हैं [] स्ट्रिंग क्लास में उपयोग किया जाता है और कभी भी आपके एप्लिकेशन में भारी स्ट्रिंग कचरा संग्रह के लिए योग्य नहीं हैं –

+1

सर्वोत्तम लिंक http://javarevisited.blogspot.com/2012/03/why-character-array-is-better-than.html – Premraj

उत्तर

17

वहाँ यदि आप एक बड़े आकार का तार का एक-स्ट्रिंग लेने के लिए और एक प्रति (आमतौर पर String(String) निर्माता के माध्यम से) नहीं करते हैं, एक स्मृति रिसाव के लिए एक संभावित है।

ध्यान दें कि यह Java 7u6 के बाद से बदल गया है। http://bugs.sun.com/view_bug.do?bug_id=4513622 देखें।

String ऑब्जेक्ट को flyweight pattern लागू करने वाली ऑब्जेक्ट के मूल मान्यताओं को अब मान्य के रूप में नहीं माना जाता है।

अधिक जानकारी के लिए this answer देखें।

+0

दोनों रणनीतियों मान्य हैं। मूल प्रत्यारोपण ठीक था; नया इम्प्ला ठीक है। लेकिन इंपोर्ट को बदलने के लिए ठीक नहीं है .... यह संगतता का एक आश्चर्यजनक ब्रेक है। वे स्पष्ट कारण के लिए यह नहीं कर सका। कुछ और चल रहा है। – irreputable

+0

@irreputable यह स्वीकार्य रूप से एक कार्यान्वयन विस्तार था जो विनिर्देश का हिस्सा नहीं था => इसे भरोसा नहीं किया जाना चाहिए था। प्रदर्शन कारणों से बदलाव किया गया है। – assylias

+2

@ वासिलियास जो एक अधिक पुलिस आउट है। लोगों ने विश्वास स्थापित किया है कि substring()/trim() ओ (1) है। चुपचाप इसे ओ (एन) में बदलना बहुत अच्छा नहीं है। और आप विभिन्न जावा संस्करणों पर लगातार व्यवहार कैसे लिखते हैं? – irreputable

4
  1. यह जावा 7u6 जब तक मामला था - आप आम तौर पर ऐसा करने से मुद्दे से निपटने होगा:

    String sub = new String(s.substring(...)); // create a new string 
    

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

  2. Java 7u6 के बाद से, एक नया स्ट्रिंग बनाया गया है और अब कोई स्मृति समस्या नहीं है।

+0

हाँ लेकिन यह एक नई समस्या पैदा करता है। यदि आप एक सफेद स्थान को ट्रिम() 'करते हैं, जो एक बहुत ही आम मामला है, तो आप' एन -1 'वर्णों की प्रतिलिपि बनाते हैं। – irreputable

+1

@irreputable आप हमेशा कोने के मामलों को ढूंढ सकते हैं जहां यह खराब प्रदर्शन करेगा। एक सामान्य उद्देश्य इंद्रधनुष का लक्ष्य औसत * पर * अच्छा प्रदर्शन करना है और ऐसा लगता है कि उस परिवर्तन से पहले कई अलग-अलग उपयोग मामलों को ध्यान में रखा गया है। – assylias

+0

वर्णों की प्रतिलिपि बनाना * बहुत तेज़ है (यह नहीं कह रहा कि इसकी लागत नहीं है)। – assylias

0

जावा 7 में, स्ट्रिंग के स्ट्रिंग को संशोधित किया गया है:

/** 
    * Returns a new string that is a substring of this string. The 
    * substring begins with the character at the specified index and 
    * extends to the end of this string. <p> 
    * Examples: 
    * <blockquote><pre> 
    * "unhappy".substring(2) returns "happy" 
    * "Harbison".substring(3) returns "bison" 
    * "emptiness".substring(9) returns "" (an empty string) 
    * </pre></blockquote> 
    * 
    * @param  beginIndex the beginning index, inclusive. 
    * @return  the specified substring. 
    * @exception IndexOutOfBoundsException if 
    *    <code>beginIndex</code> is negative or larger than the 
    *    length of this <code>String</code> object. 
    */ 
    public String substring(int beginIndex) { 
     if (beginIndex < 0) { 
      throw new StringIndexOutOfBoundsException(beginIndex); 
     } 
     int subLen = value.length - beginIndex; 
     if (subLen < 0) { 
      throw new StringIndexOutOfBoundsException(subLen); 
     } 
     return (beginIndex == 0) ? this : new String(value, beginIndex, subLen); 
    } 

इसलिए, हर आप beginIndex 0 के बराबर नहीं के साथ-स्ट्रिंग है, हम नए स्ट्रिंग वस्तु है।