Is there a particular VM implementation that behaves in that fashion?
No VM implementation that I am looking at causes that statement to become
true (even after being given a context).
Hmm. The String class code has changed. The new code avoids pinning
large blocks of RAM, but it does more System.arrayCopys.
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > count) {
throw new StringIndexOutOfBoundsException(endIndex);
}
if (beginIndex > endIndex) {
throw new StringIndexOutOfBoundsException(endIndex -
beginIndex);
}
return ((beginIndex == 0) && (endIndex == count)) ? this :
new String(offset + beginIndex, endIndex - beginIndex,
value);
}
Note that new String does not necessarily make a copy, though it does
create a new String object.
public String(String original) {
this.count = original.count;
if (original.value.length > this.count) {
// The array representing the String is bigger than the
new
// String itself. Perhaps this constructor is being
called
// in order to trim the baggage, so make a copy of the
array.
this.value = new char[this.count];
System.arraycopy(original.value, original.offset,
this.value, 0, this.count);
} else {
// The array representing the String is the same
// size as the String, so no point in making a copy.
this.value = original.value;
}
Similarly to the way a StringBuffer temporarily gets turned to a
String after a toString until it is changed is gone.
The question now is, when did it change?
This is the sort of thing I would have dug into in Java 1.0.2 days.
It happened somewhere between then and Java 1.4.2_04.