Java EE勉強会のポジペのネタです。
import java.util.*;
class Main{
// 1MBのサイズのStringを作る
static String makeHugeString(){
StringBuilder buf = new StringBuilder();
for(int i = 0 ; i < 1000000; i++){
buf.append(i % 10);
}
return buf.toString();
}
static public void main(String[] args){
List<String> list = new ArrayList<String>();
int cnt = 0;
while(true){
// 巨大な文字列を得る
String data = makeHugeString();
// 先頭文字だけを集める
list.add(data.substring(0, 1));
if(++cnt % 10 == 0) System.out.println(cnt);
}
}
}
【結果】
$ java Main
10
20
30
Exception in thread "main" java.lang.OutOfMemoryError: Java heap spaceListにsubstring()の結果を集めているのですが、30文字程度集めただけでヒープがいっぱいいっぱいになってしまいます。これはsubstring()の実装が内部ポインタだけを移動することで実現しているからです*1。
// 先頭文字だけを集める list.add(new String(data.substring(0, 1)));
と変えると大丈夫になります。これは、String(String)コンストラクタが、ポインタと内部表現の正規化を行っているためです。
ただ、こいつはドキュメントには書かれてない動きなので、積極的に使うべきではないと思います。今後のリリースでどうなるかわかりませんし≧(´▽`)≦。