String類substring方法導致的Java記憶體流失問題

來源:互聯網
上載者:User

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

想重現這個情境很容易,請看代碼。

 

 import java.util.ArrayList;<br />import java.util.List;</p><p>public class LeakTest {<br /> public static void main(String...args) {<br /> List<String> handler = new ArrayList<String>();<br /> for(int i = 0; i < 100000; i++) {<br /> Huge h = new Huge();<br /> handler.add(h.getSubString(1, 5));<br /> }<br /> }<br />}</p><p>class Huge {<br /> private String str = new String(new char[100000]);<br /> public String getSubString(int begin, int end) {<br /> return str.substring(begin, end);<br /> }<br />}

 

執行此代碼結果:

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

 

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

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

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

 

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

// Package private constructor which shares value array for speed.<br /> String(int offset, int count, char value[]) {<br />this.value = value;<br />this.offset = offset;<br />this.count = count;<br /> }

 

char[] value 數組被共用了。

 

在我們的main函數裡的迴圈中,每迴圈一次後,我們希望Huge對象被回收,且釋放它佔有的記憶體。

但實際上 private String str = new String(new char[100000]); 佔有的記憶體並不會被釋放。

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

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

 

解決方案:

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

public String getSubString(int begin, int end) {<br /> return new String(str.substring(begin, end));<br /> }

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

 

至於為什麼,看看JDK源碼,一看便知了。這裡就不貼出來了。

 

 

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

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.