讀取String#substring
(Java 1.7)的源代碼時,它看起來像重用字符數組,但具有不同的偏移量和長度。這意味着如果我有一個巨大的String
,那麼我的substring就不會被GC回收(右?)。大型子字符串的內存使用情況?
確保回收巨型String
的最簡單方法是什麼?我正在運行JavaSE-1.7。
(對於好奇,我會用Java編寫基數實施,以減少內存使用情況。在這個問題的答案是至關重要的使用比需要更多的內存,以避免基數樹)
讀取String#substring
(Java 1.7)的源代碼時,它看起來像重用字符數組,但具有不同的偏移量和長度。這意味着如果我有一個巨大的String
,那麼我的substring就不會被GC回收(右?)。大型子字符串的內存使用情況?
確保回收巨型String
的最簡單方法是什麼?我正在運行JavaSE-1.7。
(對於好奇,我會用Java編寫基數實施,以減少內存使用情況。在這個問題的答案是至關重要的使用比需要更多的內存,以避免基數樹)
對於預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
構造函數時,它將不會使用原始String
的char[]
。所以原始String
可以是GC。這實際上是應該使用String
構造函數的用例之一。在大多數情況下,我們應該使用String
文字賦值。
對於JDK 7u6 +版本
在Java 7,實施String.substring()
已經改變,現在內部使用String(char value[], int offset, int count)
構造函數(這是我們不得不手動使用舊的版本,以避免內存泄漏)。這個構造函數檢查它需要原始的String
的value[]
數組,或者更短的數組就足夠了。因此對於使用String.substring()
的JDK 7+不會造成內存泄漏問題。請看源代碼String.substring()
有趣。我的'String#String'構造函數如下所示:https://gist.github.com/JensRantil/7c08a2a0126a8f40c221我正在運行JavaSE-1.7。 – Ztyx
是的,你是對的。這是因爲在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 –
謝謝!很好的答案! – Ztyx
原始字符串將永遠是垃圾收集,如果需要的話。沒有人會反對。下面是substring()
方法的部分編碼(JDK 1.7.0_51):
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
所以,此方法返回一個全新的字符串對象或如果beginIndex 0,那麼originam字符串將被返回。我想你很關心第一個案子。在那種情況下,一旦它被創建,它就與舊的無關。
http://stackoverflow.com/questions/20081659/java-substring-memory-leak/20082582#20082582看看下面的內容。 –
你可以使用你正在使用的Java版本更新你的問題嗎? – Pshemo
Pshemo:問題已更新。 – Ztyx