2015-05-21 46 views
1

讀取String#substring(Java 1.7)的源代碼時,它看起來像重用字符數組,但具有不同的偏移量和長度。這意味着如果我有一個巨大的String,那麼我的substring就不會被GC回收(右?)。大型子字符串的內存使用情況?

確保回收巨型String的最簡單方法是什麼?我正在運行JavaSE-1.7。

(對於好奇,我會用Java編寫基數實施,以減少內存使用情況。在這個問題的答案是至關重要的使用比需要更多的內存,以避免基數樹)

+0

http://stackoverflow.com/questions/20081659/java-substring-memory-leak/20082582#20082582看看下面的內容。 –

+0

你可以使用你正在使用的Java版本更新你的問題嗎? – Pshemo

+0

Pshemo:問題已更新。 – Ztyx

回答

4

對於預JDK 7u6版本

你應該在這種情況下使用String(String)構造:

163 public String(String original) {
164 int size = original.count;
165 char[] originalValue = original.value;
166 char[] v;
167 if (originalValue.length > size) {
168 // The array representing the String is bigger than the new
169 // String itself. Perhaps this constructor is being called
170 // in order to trim the baggage, so make a copy of the array.
171 int off = original.offset;
172 v = Arrays. copyOfRange (originalValue, off, off+size);
173 } else {
174 // The array representing the String is the same
175 // size as the String, so no point in making a copy.
176 v = originalValue;
177 }
178 this.offset = 0;
179 this.count = size;
180 this.value = v;
181 }

String s = "some really looooong text"; 
String s2 = new String(s.substring(0,3)); 

當您將s.substring()的結果傳遞給String構造函數時,它將不會使用原始Stringchar[]。所以原始String可以是GC。這實際上是應該使用String構造函數的用例之一。在大多數情況下,我們應該使用String文字賦值。

對於JDK 7u6 +版本

在Java 7,實施String.substring()已經改變,現在內部使用String(char value[], int offset, int count)構造函數(這是我們不得不手動使用舊的版本,以避免內存泄漏)。這個構造函數檢查它需要原始的Stringvalue[]數組,或者更短的數組就足夠了。因此對於使用String.substring()的JDK 7+不會造成內存泄漏問題。請看源代碼String.substring()

+0

有趣。我的'String#String'構造函數如下所示:https://gist.github.com/JensRantil/7c08a2a0126a8f40c221我正在運行JavaSE-1.7。 – Ztyx

+0

是的,你是對的。這是因爲在Java7中他們改變了'String.substring()'的實現,它現在在內部使用'String(char value [],int offset,int count)'構造函數。請看源代碼http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/lang/String.java#String.substring%28int% 29 –

+0

謝謝!很好的答案! – Ztyx

0

原始字符串將永遠是垃圾收集,如果需要的話。沒有人會反對。下面是substring()方法的部分編碼(JDK 1.7.0_51):

return ((beginIndex == 0) && (endIndex == value.length)) ? this 
     : new String(value, beginIndex, subLen); 

所以,此方法返回一個全新的字符串對象或如果beginIndex 0,那麼originam字符串將被返回。我想你很關心第一個案子。在那種情況下,一旦它被創建,它就與舊的無關。

+1

「以下是substring()方法的部分代碼:」從哪個版本的Java是這個代碼? – Pshemo

+1

有許多版本的Java 7 ... – Pshemo

+0

@Pshemo,我已經更新了確切的版本。謝謝!我應該提到它。 – Kartic