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...
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 à
1000000
new 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, cararray
est un type référence. Même si vous bouclez1000000
foissubstring
, leString
dans l'objetchar[] value
est le même objet, etJDK1.7
est implémenté à l'aide de la méthodeArrays.copy
, alors vous générerez unsubstring
à chaque fois Nouvelle instancechar[] 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 :
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 :
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.