Memory leaks in Java caused by the substring method

Source: Internet
Author: User

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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.