jdk6 substring 記憶體泄露問題解析

來源:互聯網
上載者:User

標籤:

測試環境

eclipse + jdk1.6.0_25 

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());
    }
  }

} 

 運行不到一分鐘後

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) 

 好吧,記憶體溢出了

查看jdk6 substring源碼實現,看看為什嗎?我們集合中也只儲存了兩個字串,不至於說會記憶體溢出,即使我們全域變數佔用空間大的話,在我們不使用該對象時,該對象應該會被清理掉,這樣也不應該導致記憶體溢出

  public String substring(int beginIndex, int endIndex) {

    if (beginIndex < 0) {
        throw new StringIndexOutOfBoundsException(beginIndex);
    }
    if (endIndex > count) {
        throw new StringIndexOutOfBoundsException(endIndex);
    }
    if (beginIndex > endIndex) {
        throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
    }
    return ((beginIndex == 0) && (endIndex == count)) ? this :
        new String(offset + beginIndex, endIndex - beginIndex, value);
    }

 String(int offset, int count, char value[]) {

    this.value = value;
    this.offset = offset;
    this.count = count;
    }

 好吧,真相是jdk6 substring方法的實現採用的是原value保留,只是改變位移量和count;一切都已經明朗了,集合中儲存資料一直都的是全域變數的大小,所以當建立對象很多的情況下,一直累積,因為一直有引用,所以gc不掉 最終導致OOM了

第一種解決方案:修改getString方法實現,將截取後的值採用new出來的對象進行儲存

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

  } 

 第二種解決方案:jdk切到jdk1.7.0_79

為什麼切到1.7之後就可以了呢?因為jdk底層substring方法實現改了,我們還是繼續看jdk7的substring方法實現

  public String substring(int beginIndex, int endIndex) {

        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        if (endIndex > value.length) {
            throw new StringIndexOutOfBoundsException(endIndex);
        }
        int subLen = endIndex - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return ((beginIndex == 0) && (endIndex == value.length)) ? this
                : new String(value, beginIndex, subLen);
    } public String(char value[], int offset, int count) {
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count < 0) {
            throw new StringIndexOutOfBoundsException(count);
        }
        // Note: offset or count might be near -1>>>1.
        if (offset > value.length - count) {
            throw new StringIndexOutOfBoundsException(offset + count);
        }
        this.value = Arrays.copyOfRange(value, offset, offset+count);
    }

 好吧!還真改了,採用Arrays.copyOfRange了

public static char[] copyOfRange(char[] original, int from, int to) {
        int newLength = to - from;
        if (newLength < 0)
            throw new IllegalArgumentException(from + " > " + to);
        char[] copy = new char[newLength];
        System.arraycopy(original, from, copy, 0,
                         Math.min(original.length - from, newLength));
        return copy;

    } 

 最終是採用的System.arraycopy意思是將截取後的字串複製一份出來

這樣就解決了jdk6記憶體溢出的問題了 

 

jdk6 substring 記憶體泄露問題解析

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.