java - JDK6中String的subString方法内存泄露及溢出问题
怪我咯
怪我咯 2017-04-18 10:32:32
0
4
592

JDK6中的subString方法会存在内存泄露问题,是由于源字符串中的value数组不会被GC回收。
看到一篇文章(http://www.cnblogs.com/hxy520...),里面有如下代码,说在JDK6下会报内存溢出的错误。请问下,为什么会产生?list的每次add不是只加一点点内存占用么?

public class SubMain {

  private String strs = new String(new byte[100000]);

  String getString() {
    return this.strs.substring(0, 2);
  }

  public static void main(String[] args) {
    List<String> list = new ArrayList<String>();
    SubMain sub = new SubMain();
    for (int i = 0; i < 1000000; i++) {
      list.add(sub.getString());
    }
  }

}

/*Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.lang.StringCoding$StringDecoder.decode(StringCoding.java:133)
    at java.lang.StringCoding.decode(StringCoding.java:173)
    at java.lang.StringCoding.decode(StringCoding.java:185)
    at java.lang.String.<init>(String.java:570)
    at java.lang.String.<init>(String.java:593)
    at com.jd.o2o.substring.SubMain.<init>(SubMain.java:8)
    at com.jd.o2o.substring.SubMain.main(SubMain.java:18)*/

其他参考文章:http://blog.csdn.net/longzuyu...,
http://www.wtoutiao.com/p/jfc...

怪我咯
怪我咯

走同样的路,发现不同的人生

全員に返信(4)
小葫芦

前の子供用シューズでも、jdk1.6 メソッドでも、あなたが言及したメモリ リークの問題が発生しないことが非常に明確になりました。
メモリ不足の理由は、1000000 new String(new byte[100000]) オブジェクトを適用するのに十分なメモリがないためです。 1000000new String(new byte[100000])对象。


还有,按照你的逻辑来实现的话,JDK1.6的实现方式绝对是占用更少内存的,因为array是引用类型。即便你循环1000000substring,在String对象中的char[] value也是同一个对象,而JDK1.7使用Arrays.copy的方式实现,那你每一次substring就将会生成一个新的char[] value

また、array は参照型であるため、ロジックに従って実装された場合、JDK1.6 の実装は確実にメモリ占有量が少なくなります。 1000000substring をループしたとしても、String オブジェクトの char[] value は同じオブジェクトです。 JDK1.7Arrays.copy を使用して実装されており、substring 値ごとに新しい char[] を生成します。コード>インスタンス。 🎜
いいねを押す +0
阿神

まず for ループの外で java SubMain sub = new SubMain(); を初期化する必要があります。
for ループで毎回ヒープ上に SubMain を作成するため、各 SubMain は少なくとも 100k を占有し、それを 1,000,000 回繰り返すことになり、100G のヒープ領域が必要になります。同時に、SubMain への参照はリストに保存され、gc もフル gc もそれを再利用できず、確実にメモリがオーバーフローします。

同時に、メモリ割り当てについて議論するときは、少なくとも仮想マシン構成の -Xms、-Xmx、-Xmn、-XX:SurvivorRatio を提供してください。

いいねを押す +0
刘奇

この質問は非常に興味深いもので、私はそれを調べて知りました。著者の理解では、subString はせいぜい元の文字列メモリをリサイクルせず、リストのループによってメモリが少しずつ増加するだけです。時間。後でプログラムを注意深く見てみましょう:

リーリー

strings は SubMain のインスタンス変数であり、SubMain はループによって 1,000,000 回インスタンス化されているため、結果は想像できます...

さらに、この問題は JDK7 update6 で修正されました。
古いバージョンの JDK の場合は、次の方法を使用できます:

リーリー
いいねを押す +0
迷茫

List は常にヒープ メモリへの参照を保持し、メモリがオーバーフローしないようにしてください。

いいねを押す +0
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!