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

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 list = new ArrayList(); 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.(String.java:570) at java.lang.String.(String.java:593) at com.jd.o2o.substring.SubMain.(SubMain.java:8) at com.jd.o2o.substring.SubMain.main(SubMain.java:18)*/

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

怪我咯
怪我咯

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

membalas semua (4)
小葫芦

前面的童鞋也讲的很明白了,即使是jdk1.6的方式也不会存在你所说的内存泄露问题。
导致你内存不足的原因是因为你本身就没有足够的内存申请1000000new String(new byte[100000])对象。


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

    阿神

    你需要先把java SubMain sub = new SubMain();提到for循环外面初始化。
    因为你每次for循环都在堆上创建SubMain,每个SubMain都至少占用了100k,你重复1000000次,这得需要100G的堆空间。同时list里面保存了SubMain的引用,gc和full gc都无法回收,肯定会内存溢出!

    同时,讨论内存分配,至少要把虚拟机配置的-Xms,-Xmx, -Xmn, -XX:SurvivorRatio提供出来啊!

      刘奇

      这个问题蛮有意思,我特意查了一下, 学习了,楼主的理解是subString最多导致原来的string内存没被回收,list的循环最多也就每次增加一点点内存。后来我仔细看了下程序:

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

      因为strings是SubMain的实例变量,而SubMain又被循环实例化了1000000次,结果可想而知...

      另外, 这个问题再JDK7 update6已经被修复了。
      如果是老版本JDK,可以用这样的方式:

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

        死劲的往堆内存中放数据 list一直保留堆内存的引用 肯定gc不回收喽 你的内存必须溢出

          Muat turun terkini
          Lagi>
          kesan web
          Kod sumber laman web
          Bahan laman web
          Templat hujung hadapan
          Tentang kita Penafian Sitemap
          Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!