此問(wèn)題在項(xiàng)目中被發(fā)現(xiàn),經(jīng)查看JDK源碼(JDK1.6),String類的public String substring(int beginIndex, int endIndex)的實(shí)現(xiàn)讓我很意外。
想重現(xiàn)這個(gè)場(chǎng)景很容易,請(qǐng)看代碼。

2

3

4

5


6

7

8

9

10

11

12

13

14

15

16

17

18

19

執(zhí)行此代碼結(jié)果:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
問(wèn)題就出在Huge類的 getSubString 方法,它調(diào)用了String類的substring方法。
來(lái)讓我們看看 substring 類的實(shí)現(xiàn)吧,JDK源碼如下:

2

3

4

5

6

7

8

9

10

11

12

13

再讓我們接下來(lái)看看 new String(offset + beginIndex, endIndex - beginIndex, value); 的實(shí)現(xiàn):

2

3

4

5

6

char[] value 數(shù)組被共享了。
在我們的main函數(shù)里的循環(huán)中,每循環(huán)一次后,我們希望Huge對(duì)象被回收,且釋放它占有的內(nèi)存。
但實(shí)際上 private String str = new String(new char[100000]); 占有的內(nèi)存并不會(huì)被釋放。
因?yàn)?我們通過(guò) Huge 類的 getSubString 方法得到的 String 對(duì)象還存在(存在于handler的列表中),
它雖然是 length 只有 4 的對(duì)象,卻享有著 char[100000] 的空間。
解決方案:
可以修改Huge 類的 getSubString 方法如下:

2

3

只要再套一個(gè)String的構(gòu)造方法即可。
至于為什么,看看JDK源碼,一看便知了。這里就不貼出來(lái)了。
唉,以后寫(xiě)代碼得多多小心啊。
----2010年08月27日
本文為原創(chuàng),歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明出處BlogJava。