Method Area and runtime constant pool overflow
Because the runtime frequent volume pool is part of the method area, the overflow tests in these two areas are put together. As mentioned above, JDK 1.7 is gradually "replaced permanently". Here, we will test the code to observe the actual impact of this issue on the program.
String. intern () is a native method. Its function is to return a String object representing the string in the pool if the String constant pool already contains a string equal to this string object. Otherwise, add the string contained in this string object to the constant pool and return a reference to this string object. In JDK 1.6 and earlier versions, since the constant pool is allocated for a permanent period of time, we can use-XX: permsize and-XX: maxpermsize to limit the size of the method area, this indirectly limits the capacity of the constant pool, as shown in the code list 2-6.
Code List 2-6 memory overflow exceptions caused by frequent pool operations
1/** 2 * VM ARGs:-XX: permsize = 10 m-XX: maxpermsize = 10 m 3 * @ author zzm 4 */5 public class runtimeconstantpooloom {6 7 public static void main (string [] ARGs) {8 // use list to keep constant pool reference, avoiding full GC collection of constant pool behavior 9 list <string> List = new arraylist <string> (); 10 // 10 MB permsize is sufficient to generate OOM 11 int I = 0 in the Integer Range; 12 while (true) {13 list. add (string. valueof (I ++ ). intern (); 14} 15} 16}
Running result:
- Exception in thread "Main" Java. Lang. outofmemoryerror: permgen Space
- At java. Lang. String. Intern (native method)
- At org. fenixsoft. oom. runtimeconstantpooloom. Main (runtimeconstantpooloom. Java: 18)
From the running results, we can see that the runtime pool overflows. The message following outofmemoryerror is "permgen space ", this indicates that the runtime constant pool is part of the Method Area (permanent generation in the hotspot virtual machine.
Using JDK 1.7 to run this program won't get the same result, and the while loop will continue. The implementation of this string constant pool can also lead to a more interesting impact, as shown in the code list 2-7.
Code List 2-7 string. Intern () returns the referenced test
1 public class runtimeconstantpooloom {2 3 Public static void main (string [] ARGs) {4 public static void main (string [] ARGs) {5 string str1 = new stringbuilder ("computer "). append ("software "). tostring (); 6 system. out. println (str1.intern () = str1); 7 8 string str2 = new stringbuilder ("Ja "). append ("va "). tostring (); 9 system. out. println (str2.intern () = str2); 10} 11}
When this code is run in JDK 1.6, two false values are obtained. When it is run in JDK 1.7, a true value and a false value are obtained. The reason for the difference is: in JDK 1.6, the intern () method will copy the string instance encountered for the first time to the permanent generation, and the return is also a reference to the string instance in the permanent generation, the string instance created by stringbuilder is on the java stack. Therefore, if it is not the same reference, false is returned. The intern () Implementation of JDK 1.7 (and some other virtual machines, such as jrockit) will not copy instances, but will only record the instance reference for the first time in the constant pool, so intern () the returned reference is the same as the string instance created by stringbuilder. Returns false for str2 because the string "Java" is executing stringbuilder. tostring () has appeared before. It is referenced in the String constant pool and does not conform to the "first appearance" principle. The "computer software" string is the first appearance, therefore, true is returned.
The method area stores information about the class, such as the class name, access modifier, constant pool, field description, and method description. For testing in these regions, the basic idea is that a large number of classes are generated during the runtime to fill the method zone until the overflow occurs. Although Java SE APIs can also be used to dynamically generate classes (for example, generatedconstructoraccessor and dynamic proxy during reflection), this experiment is quite troublesome. In the code list 2-8, the author uses cglib to directly operate on bytecode to generate a large number of dynamic classes.
It is worth noting that the scenario we simulate in this example is not purely an experiment, and such an application is often used in practical applications: Many mainstream frameworks currently, for example, spring and hibernate, cglib and other bytecode technologies are used for class enhancement. The more enhanced classes, the larger the method area is required to ensure that the dynamically generated class can be loaded into the memory. In addition, dynamic languages on JVM (such as groovy) Usually create classes to achieve language dynamics. With the popularity of such languages, it is more and more prone to overflow scenarios similar to the code list 2-8.
Code List 2-8 memory overflow exception in the method area using cglib
1 /** 2 * VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M 3 * @author zzm 4 */ 5 public class JavaMethodAreaOOM { 6 7 public static void main(String[] args) { 8 while (true) { 9 Enhancer enhancer = new Enhancer(); 10 enhancer.setSuperclass(OOMObject.class); 11 enhancer.setUseCache(false); 12 enhancer.setCallback(new MethodInterceptor() { 13 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { 14 return proxy.invokeSuper(obj, args); 15 } 16 }); 17 enhancer.create(); 18 } 19 } 20 21 static class OOMObject { 22 23 } 24 }
Running result:
- Caused by: Java. Lang. outofmemoryerror: permgen Space
- At java. Lang. classloader. defineclass1 (native method)
- At java. Lang. classloader. defineclasscond (classloader. Java: 632)
- At java. Lang. classloader. defineclass (classloader. Java: 616)
- ... 8 more
Method zone overflow is also a common memory overflow exception. If a class is to be reclaimed by the garbage collector, the condition is harsh. In applications that frequently generate a large number of classes dynamically, pay special attention to the collection of classes. In addition to the cglib bytecode enhancement and dynamic language used by the above mentioned programs, the following common scenarios are as follows: A large number of JSP or applications that dynamically generate JSP files (JSPs need to be compiled into Java classes during the first run), osgi-based applications (even the same class file, loaded by different loaders will also be considered as different classes.
Method Area and runtime constant area Overflow