This problem was found in the project. I was surprised by the implementation of the public string substring (INT beginindex, int endindex) of the string class in JDK source code (jdk1.6.
It is easy to reproduce this scenario. Please refer to the code.
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/>}</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/>}
Run the following code:
Exception in thread "Main" Java. Lang. outofmemoryerror: Java heap Space
The problem lies in the getsubstring method of the huge class, which calls the substring method of the string class.
Let's take a look at the implementation of the substring class. The JDK source code is as follows:
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) & (endinde X = count ))? This: <br/> New String (Offset + beginindex, endindex-beginindex, value); <br/>}
Let's take a look at the implementation of 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/>}
The Char [] value array is shared.
In the loop in our main function, after each loop, we want the huge object to be recycled and the memory occupied by it will be released.
But in fact, private string STR = new string (New char [100000]); the occupied memory is not released.
Because the string object obtained through the getsubstring method of the huge class still exists (in the handler list ),
Although it is an object with only length 4, it enjoys the space of char [100000.
Solution:
You can modify the getsubstring method of the huge class as follows:
Public String getsubstring (INT begin, int end) {<br/> return new string (Str. substring (begin, end); <br/>}
You only need to set another string constructor.
Let's look at the JDK source code. I will not post it here.
Alas, be careful when writing code in the future.