>  Q&A  >  본문

java - JDK6中String的subString方法内存泄露及溢出问题

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

怪我咯怪我咯2711일 전594

모든 응답(4)나는 대답할 것이다

  • 高洛峰

    高洛峰2017-04-18 10:34:32

    이전 아동용 신발도 jdk1.6 방식에서도 언급한 메모리 누수 문제가 없음을 매우 명확하게 밝혔습니다.
    메모리가 부족해지는 이유는 1000000new String(new byte[100000])개체에 지원하기에는 메모리가 부족하기 때문입니다.


    또한 논리에 따라 구현하면 JDK1.6은 참조 유형이므로 array 구현은 확실히 메모리를 덜 차지합니다. 1000000substring을 반복하더라도 String 객체의 char[] value은 동일한 객체이고 JDK1.7Arrays.copy 메서드를 사용하여 구현되므로 매번 substring이 생성됩니다. 새로운 char[] value 인스턴스.

    회신하다
    0
  • 阿神

    阿神2017-04-18 10:34:32

    먼저 for 루프 외부에서 java SubMain sub = new SubMain();를 초기화해야 합니다.
    for 루프에서 매번 힙에 SubMain을 생성하기 때문에 각 SubMain은 최소 100k를 차지하고 이를 1,000,000번 반복하므로 100G의 힙 공간이 필요합니다. 동시에, SubMain에 대한 참조는 목록에 저장됩니다. gc나 full gc 모두 이를 재활용할 수 없으며 메모리는 확실히 오버플로됩니다!

    동시에 메모리 할당을 논의할 때 최소한 가상 머신 구성의 -Xms, -Xmx, -Xmn, -XX:SurvivorRatio를 제공하세요!

    회신하다
    0
  • 怪我咯

    怪我咯2017-04-18 10:34:32

    이 질문은 매우 흥미롭습니다. 확인해 보고 알게 된 점은 subString이 기껏해야 원래 문자열 메모리를 재활용하지 못하게 하고 목록의 루프가 메모리를 약간만 늘릴 뿐이라는 것입니다. 매번 조금. 나중에 프로그램을 주의 깊게 살펴봤습니다.

    으아아아

    문자열은 SubMain의 인스턴스 변수이고 SubMain은 루프에 의해 1,000,000번 인스턴스화되었으므로 결과를 상상할 수 있습니다...

    또한 이 문제는 JDK7 업데이트 6에서 수정되었습니다.
    JDK가 이전 버전인 경우 다음 방법을 사용할 수 있습니다.

    으아아아

    회신하다
    0
  • 迷茫

    迷茫2017-04-18 10:34:32

    가능한 한 데이터를 힙 메모리에 넣으세요. 목록에는 항상 힙 메모리에 대한 참조가 유지됩니다. GC는 이를 재활용하지 않을 것입니다.

    회신하다
    0
  • 취소회신하다