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

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...

怪我咯
怪我咯

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

répondre à tous(4)
小葫芦

Les chaussures pour enfants précédentes l'ont également indiqué très clairement. Même la méthode jdk1.6 n'aura pas le problème de fuite de mémoire que vous avez mentionné.
La raison pour laquelle vous manquez de mémoire est que vous n'avez pas assez de mémoire pour postuler à 1000000new String(new byte[100000]) objets.


De plus, si elle est implémentée selon votre logique, l'implémentation de JDK1.6 occupera certainement moins de mémoire, car array est un type référence. Même si vous bouclez 1000000 fois substring, le String dans l'objet char[] value est le même objet, et JDK1.7 est implémenté à l'aide de la méthode Arrays.copy, alors vous générerez un substring à chaque fois Nouvelle instance char[] value.

阿神

Vous devez d'abord initialiser java SubMain sub = new SubMain(); en dehors de la boucle for.
Étant donné que vous créez un SubMain sur le tas à chaque fois dans la boucle for, chaque SubMain occupe au moins 100 000 $ et vous le répétez 1 000 000 de fois, ce qui nécessite 100 Go d'espace sur le tas. Dans le même temps, la référence à SubMain est enregistrée dans la liste. Ni gc ni full gc ne peuvent la recycler, et la mémoire va définitivement déborder !

En même temps, lorsque vous discutez de l'allocation de mémoire, fournissez au moins les -Xms, -Xmx, -Xmn, -XX:SurvivorRatio de la configuration de la machine virtuelle !

刘奇

Cette question est assez intéressante. Je l'ai vérifiée et j'en ai entendu parler. L'auteur comprend que subString empêchera tout au plus le recyclage de la mémoire de chaîne d'origine, et la boucle de la liste ne fera qu'augmenter un peu la mémoire. un peu à chaque fois. Plus tard, j'ai regardé attentivement le programme :

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>();
    for (int i = 0; i < 1000000; i++) {
      SubMain sub = new SubMain();
      list.add(sub.getString());
    }
  }
} 

Parce que les chaînes sont une variable d'instance de SubMain et que SubMain a été instancié 1 000 000 de fois par la boucle, les résultats peuvent être imaginés...

De plus, ce problème a été corrigé dans la mise à jour 6 du JDK7.
S'il s'agit d'une ancienne version du JDK, vous pouvez utiliser cette méthode :

String s2 = new String(s1.substring(0,2));
迷茫

Mettez les données dans la mémoire tas aussi fort que possible. La liste conserve toujours les références à la mémoire tas. Je suis sûr que GC ne la recyclera pas. Votre mémoire doit déborder.

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal