In Java we don't have to worry about the release of memory, the JVM provides a memory management mechanism, and the garbage collector helps reclaim unwanted objects. However, some improper use in practice can still cause a series of memory problems, common is memory leaks and memory overflow
memory Overflow (outof memory): In layman's words, it is not enough, for example, to create a large object in an infinite loop, which can quickly cause a memory overflow.
memory leak (leakof Memories): refers to the allocation of memory for an object, when the object is no longer in use when not released in a timely manner, causing the memory unit to occupy, so that the actual available memory is reduced, as if the memory leaks.
Memory leaks caused by the substring method
substring (int beginindex, int endndex) is a method of the string class, but the implementation of this method in JDK6 and JDK7 is completely different (although they all achieve the same effect). Understanding the differences in their implementation details can help you to use them better because improper use of substring in JDK1.6 can lead to serious memory leak issues.
1, the role of substring
The substring (int beginindex, int endIndex) method returns a substring, starting with the beginindex of the parent string and ending with endindex-1. The index of the parent string starts with 0, and the substring contains beginindex and does not contain endindex.
String x= "abcdef"; x= str.substring (1,3); SYSTEM.OUT.PRINTLN (x);
The output of the above program is "BC"
2. Principle of realization
The string class is immutable, and when X is re-assigned in the second sentence above, it points to a new string object, as shown in the following picture:
However, this picture does not accurately explain or represent the actual situation in the heap, and when substring is called, what really happens is the difference between the two.
Implementation of substring in JDK6
The string object is stored as a char array, with 3 fields in the String class: char[] value, int offset, int count, respectively, to store the actual character array, the starting position of the array, and the number of characters in the string. A string can be determined by these 3 variables. When the substring method is called, it creates a new string, but the above char array value will still use that value from the original parent array. The only difference between the parent and the sub-arrays is that the value of count and offset is different, and the following diagram illustrates the process in an image.
Take a look at the JDK6 in the substring implementation source:
Public String substring (int beginindex, int endIndex) {if (Beginindex < 0) { throw new stringindexoutofboundsexcept Ion (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);//using the same char array as the parent string value }
String (int offset, int count, Char value[]) {this.value = Value;this.offset = Offset;this.count = count; }
This causes a memory leak leak:
String str = "Abcdefghijklmnopqrst"; String sub = str.substring (1, 3); str = NULL;
This simple program has two string variables, str, sub. The sub string is intercepted by the parent string str, and if the above program runs in JDK1.6, we know that the memory space allocation of the array is on the heap, then the inner Char array value of sub and STR is common, that is, the character a~ Character T consists of a char array, and the only difference between STR and sub is the fact that the beginindex and the character length count differ in the array. In the third sentence, we make the STR reference NULL, which is intended to free up the space used by STR, but at this point the GC cannot reclaim the large char array because it is also referenced inside the sub string, although the sub only intercepts a small part of the large array. When STR is a very large string, this waste is very obvious and even brings performance problems, which can be solved by the following methods:
String str = "Abcdefghijklmnopqrst"; String sub = str.substring (1, 3) + ""; str = null;
Using the concatenation technique of the string, it creates a new string, which uses a new internal char array to store the characters that it actually needs, so that the char array of the parent array is not referenced, so str=null, The space occupied by the entire STR is recycled at the time of the next GC recovery. But this writing is obviously not good-looking, so in the JDK7, substring was re-implemented.
Implementation of substring in JDK7
The implementation of the substring is improved in JDK7, and it is actually a new char array created in the heap for the truncated substring to hold the characters of the substring. The following diagram illustrates the implementation of substring in JDK7:
View the implementation of the substring method of the string class in JDK7 source code:
Public String substring (int beginindex, int endIndex) { if (Beginindex < 0) { throw new Stringindexoutofboundse Xception (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 Stringindexoutofboundsexceptio n (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); }
Copyofrange methods for the arrays class:
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]; is the creation of a new char array system.arraycopy (original, from, copy, 0, math.min (Original.length-from, newlength)); return copy; }
You can find that you are going to create a new char array for the substring to store the characters in the substring. This way the string and the parent string are not necessarily related, when the parent string reference fails, the GC will be in time to reclaim the memory space occupied by the parent string.
Memory leaks in Java caused by the substring method