阅读String#substring
(Java 1.7)的源代码,看起来它重用了字符数组,但具有不同的偏移量和长度。这意味着,如果我有一个巨型的String
,我将子串起来,GC的初始字符串将永远不会被回收(对吧?)。
确定巨型String
被收回的最简单方法是什么?我正在运行JavaSE-1.7。
(好奇的是,我将用Java编写基数实现以减少内存使用。这个问题的答案对于避免基数树使用的内存超过必要而非常重要。
答案 0 :(得分: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
构造函数时,它将不会使用原始char[]
的{{1}}。所以原来的String
可以是GC。这实际上是应该使用String
构造函数的用例之一。虽然在大多数情况下我们应该使用String
文字作业。
对于JDK 7u6 +版本
在Java 7中,String
的实现已经改变,现在内部使用String.substring()
构造函数(我们必须在旧版本中手动使用以避免内存泄漏)。此构造函数检查它是否需要原始String(char value[], int offset, int count)
的{{1}}数组,否则较短的数组就足够了。因此对于使用String
的JDK 7+不会造成内存泄漏问题。请查看源代码String.substring()
答案 1 :(得分:0)
如果需要,原始字符串将始终为垃圾收集。没人会反对。以下是substring()
方法的部分代码(JDK 1.7.0_51):
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
因此,此方法返回一个全新的String对象,或者如果beginIndex为0,则返回原始String。我想你担心第一个案子。在这种情况下,它与旧版本创建后无关。