<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    ALL is Well!

    敏捷是一條很長的路,摸索著前進著

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      30 隨筆 :: 23 文章 :: 71 評論 :: 0 Trackbacks

    此問題在項目中被發現,經查看JDK源碼(JDK1.6),String類的public String substring(int beginIndex, int endIndex)的實現讓我很意外。

    想重現這個場景很容易,請看代碼。

     1import java.util.ArrayList;
     2import java.util.List;
     3
     4public class LeakTest {
     5    public static void main(Stringargs) {
     6        List<String> handler = new ArrayList<String>();
     7        for(int i = 0; i < 100000; i++{
     8            Huge h = new Huge();
     9            handler.add(h.getSubString(15));
    10        }

    11    }

    12}

    13
    14class Huge {
    15    private String str = new String(new char[100000]);
    16    public String getSubString(int begin, int end) {
    17        return str.substring(begin, end);
    18    }

    19}

    執行此代碼結果:

    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

     

    問題就出在Huge類的 getSubString 方法,它調用了String類的substring方法。

    來讓我們看看 substring 類的實現吧,JDK源碼如下:

     1    public String substring(int beginIndex, int endIndex) {
     2    if (beginIndex < 0{
     3        throw new StringIndexOutOfBoundsException(beginIndex);
     4    }

     5    if (endIndex > count) {
     6        throw new StringIndexOutOfBoundsException(endIndex);
     7    }

     8    if (beginIndex > endIndex) {
     9        throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
    10    }

    11    return ((beginIndex == 0&& (endIndex == count)) ? this :
    12        new String(offset + beginIndex, endIndex - beginIndex, value);
    13    }

    再讓我們接下來看看 new String(offset + beginIndex, endIndex - beginIndex, value); 的實現:


    1    // Package private constructor which shares value array for speed.
    2    String(int offset, int count, char value[]) {
    3    this.value = value;
    4    this.offset = offset;
    5    this.count = count;
    6    }


    char[] value 數組被共享了。

     

    在我們的main函數里的循環中,每循環一次后,我們希望Huge對象被回收,且釋放它占有的內存。

    但實際上 private String str = new String(new char[100000]); 占有的內存并不會被釋放。

    因為 我們通過 Huge 類的 getSubString 方法得到的 String 對象還存在(存在于handler的列表中),

    它雖然是 length 只有 4 的對象,卻享有著 char[100000] 的空間。

     

    解決方案:

    可以修改Huge 類的 getSubString 方法如下:

    1    public String getSubString(int begin, int end) {
    2        return new String(str.substring(begin, end));
    3    }

    只要再套一個String的構造方法即可。

     

    至于為什么,看看JDK源碼,一看便知了。這里就不貼出來了。

     

     

    唉,以后寫代碼得多多小心啊。


    ----2010年08月27日

    本文為原創,歡迎轉載,轉載請注明出處BlogJava
    posted on 2010-09-01 12:41 李 明 閱讀(1471) 評論(0)  編輯  收藏 所屬分類: Java
    主站蜘蛛池模板: 久久精品蜜芽亚洲国产AV| 亚洲一级片内射网站在线观看| 免费的黄网站男人的天堂| 精品久久香蕉国产线看观看亚洲| 97免费人妻在线视频| 一级特黄录像视频免费| 亚洲中文字幕无码亚洲成A人片| 五月天网站亚洲小说| 亚洲一区爱区精品无码| 四虎影在线永久免费观看| 24小时免费直播在线观看| 在线观看特色大片免费网站| 免费一级全黄少妇性色生活片| 亚洲AV无码男人的天堂| 亚洲欧美日韩一区二区三区| 亚洲色欲色欲www| 亚洲αⅴ无码乱码在线观看性色| 亚洲中文字幕无码中文字| 亚洲精品456人成在线| 久久乐国产综合亚洲精品| 亚洲日本VA午夜在线影院| 亚洲日韩看片无码电影| MM1313亚洲国产精品| 美女黄色毛片免费看| eeuss草民免费| 5g影院5g天天爽永久免费影院 | 最近中文字幕无吗免费高清 | 国产免费久久精品99久久| 成人精品一区二区三区不卡免费看 | 欧洲精品码一区二区三区免费看| 人人公开免费超级碰碰碰视频| 中文字幕无码免费久久| 日本XXX黄区免费看| 亚洲精品视频免费| 亚洲美免无码中文字幕在线| 亚洲精品天堂成人片AV在线播放 | 亚洲国产成人91精品| 免费夜色污私人影院网站| 国产免费久久精品99re丫y| 亚洲精品国产高清不卡在线| 亚洲伊人久久大香线焦|