Java program performance optimization - memory leak of subString() method

In section 3.12 of "Java Program Performance Optimization", an example is used to illustrate that the use of subString methods in versions before Java 6 (which has been solved in Java 7) may cause performance problems, but it does not explain why performance problems occur. Try to analyze this problem at the memory model level.

 

Source code:

 

public class Test {
	public static void main(String[] args) {
		List<String> handler = new ArrayList<String>();

		for (int i = 0; i < 1000; i++) {
			HugeStr h = new HugeStr(); // Line 1
			//ImprovedHugeStr h = new ImprovedHugeStr(); // Line 2
			handler.add(h.getSubString(1, 5)); // Line 3
		}
	}

	static class HugeStr {
		private String str = new String(new char[100000]);
		
		public String getSubString(int begin, int end) {
			return str.substring(begin, end);
		}
	}
	
	static class ImprovedHugeStr {
		private String str = new String(new char[100000]);
		
		public String getSubString(int begin, int end) {
			return new String(str.substring(begin, end));
		}
	}
}
 

 

This is a simple memory allocation diagram of a for loop of HugeStr.



 illustrate:

Line 1 actually does two operations, creating a new HugeStr object in the heap, and pointing h to the newly created HugeStr object in the heap; and the HugeStr object contains a str attribute. Similarly, at this moment str Will point to another String object in memory, the String object contains a value attribute pointing to a 100000-length array.

Line 3 focuses on the operation of h.getSubString(). Before Java 7, a new string will be created here, and the reference of the value of the original string will be passed to the new string, as in the third picture of 3.12. As shown, the value attribute of the new string points to the very long string on Line 1.

When the loop ends, the reference of h becomes an invalid reference, then other associated invalid references are shown as red X in the figure. However, an array of length 100000 cannot be determined to be an invalid reference, because the object generated by Line 3 will be placed in the collection after the ArrayList.add() method is executed.

 

CompareImprovedHugeStr



 

 

Description: The only difference between ImprovedHugeStr and HugeStr is that a new string is created in the getSubstring() method, and just for this new operation, Java will copy the original value array and generate a new array, which makes a large array The reference becomes invalid after the cycle, and it will be collected by the garbage collector when it needs to perform gc. On the JDK source code.

 

public String(String original) {
	int size = original.count;
	char[] originalValue = original.value;
	char [] v;
  	if (originalValue.length > size) {
 	    // The array representing the String is bigger than the new
 	    // String itself.  Perhaps this constructor is being called
 	    // in order to trim the baggage, so make a copy of the array.
            int off = original.offset;
            v = Arrays.copyOfRange(originalValue, off, off+size);
 	} else {
 	    // The array representing the String is the same
 	    // size as the String, so no point in making a copy.
	    v = originalValue;
 	}
	this.offset = 0;
	this.count = size;
	this.value = v;
    }

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326248540&siteId=291194637
Recommended