Home > Java > Java Tutorial > body text

Java common memory overflow exceptions and code implementation

黄舟
Release: 2017-02-23 10:38:04
Original
1284 people have browsed it

Java Heap OutOfMemoryError

The Java heap is used to store object instances, so if we continue to create objects and ensure that there is a reachable path between the GC Root and the created object to prevent the object from being garbage collected, Then when too many objects are created, it will cause insufficient memory in the heap, which will trigger an OutOfMemoryError exception.

/**
 * @author xiongyongshun
 * VM Args: java -Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError
 */
public class OutOfMemoryErrorTest {
    public static void main(String[] args) {
        List list = new ArrayList<>();
        int i = 0;
        while (true) {
            list.add(i++);
        }
    }
}
Copy after login

The above is a code that triggers an OutOfMemoryError exception. We can see that it continuously Create objects independently and save the objects in the list to prevent them from being garbage collected. Therefore, when there are too many objects, the heap memory will overflow.

Through java -Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError we set the heap memory to 10 MB, and use the parameter -XX:+HeapDumpOnOutOfMemoryError to let the JVM print out the current memory snapshot when an OutOfMemoryError exception occurs for subsequent convenience Analysis.

After compiling and running the above code, there will be the following output:

>>> java -Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError com.test.OutOfMemoryErrorTest                                                                                            16-10-02 23:35
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid1810.hprof ...
Heap dump file created [14212861 bytes in 0.125 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at java.util.Arrays.copyOf(Arrays.java:3210)
        at java.util.Arrays.copyOf(Arrays.java:3181)
        at java.util.ArrayList.grow(ArrayList.java:261)
        at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235)
        at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227)
        at java.util.ArrayList.add(ArrayList.java:458)
        at com.test.OutOfMemoryErrorTest.main(OutOfMemoryErrorTest.java:15)
Copy after login

Java stackStackOverflowError

We know that the runtime data area of ​​the JVM There is a memory area called the virtual machine stack. The role of this area is: each method will create a stack frame when executed, which is used to store local variable tables, operand stacks, method exits and other information.

So we can create an infinitely recursive recursive call. When the recursion depth is too large, the stack space will be exhausted, which will lead to a StackOverflowError exception.

The following is the specific code:

/**
 * @author xiongyongshun
 * VM Args: java -Xss64k
 */
public class OutOfMemoryErrorTest {
    public static void main(String[] args) {
        stackOutOfMemoryError(1);
    }
    public static void stackOutOfMemoryError(int depth) {
        depth++;
        stackOutOfMemoryError(depth);
    }
}
Copy after login

When the above code is compiled and run, the following exception message will be output:

Exception in thread "main" java.lang.StackOverflowError
    at com.test.OutOfMemoryErrorTest.stackOutOfMemoryError(OutOfMemoryErrorTest.java:27)
Copy after login

Method area memory overflow

, 因为 JDK8 已经移除了永久代, 取而代之的是 metaspace, 因此在 JDK8 中, 下面两个例子都不会导致 java.lang.OutOfMemoryError: PermGen space 异常.
Copy after login


Runtime constant pool overflow

In Java 1.6 and previous HotSpot JVM versions, there is the concept of the permanent generation, that is, the generational collection mechanism of GC is extended to the method area. In the method area , a part of the memory is used to store the constant pool, so if there are too many constants in the code, the constant pool memory will be exhausted, leading to memory overflow. So how to add a large number of constants to the constant pool? At this time, you need to rely on String. intern() method. The function of String.intern() method is: if the value of this String already exists in the constant pool, this method returns the reference of the corresponding string in the constant pool; otherwise, the value contained in this String is added. to the constant pool, and returns a reference to this String object. In JDK 1.6 and previous versions, the constant pool is allocated in the permanent generation, so we can set the parameters "-XX:PermSize" and "-XX:MaxPermSize" to Indirectly limit the size of the constant pool.

, 上面所说的 String.intern() 方法和常量池的内存分布仅仅针对于 JDK 1.6 及之前的版本, 在 JDK 1.7 或以上的版本中, 由于去除了永久代的概念, 因此内存布局稍有不同.
Copy after login


The following is a code example to implement constant pool memory overflow:

/**
 * @author xiongyongshun
 * VM Args:  -XX:PermSize=10M -XX:MaxPermSize=10M 
 */
public class RuntimeConstantPoolOOMTest {
    public static void main(String[] args) {
        List list = new ArrayList();
        int i = 0;
        while (true) {
            list.add(String.valueOf(i++).intern());
        }
    }
}
Copy after login

We see , in this example, the String.intern() method is used to add a large number of string constants to the constant pool, thus causing the memory overflow of the constant pool.

We compile and compile through JDK1.6 Running the above code, there will be the following output:

Exception in thread "main" java.lang.OutOfMemoryError: PermGen space
        at java.lang.String.intern(Native Method)
        at com.test.RuntimeConstantPoolOOMTest.main(RuntimeConstantPoolOOMTest.java:16)
Copy after login
, 如果通过 JDK1.8 来编译运行上面代码的话, 会有如下警告, 并且不会产生任何的异常:
Copy after login
>>> java -XX:PermSize=10M -XX:MaxPermSize=10M com.test.RuntimeConstantPoolOOMTest                                                                                                  16-10-03 0:23
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=10M; support was removed in 8.0
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=10M; support was removed in 8.0
Copy after login

Memory overflow in the method area

The method area is used to store Class-related information, such as class name, class access Modifiers, field descriptions, method descriptions, etc. Therefore, if the method area is too small and too many classes are loaded, the memory in the method area will overflow.

//VM Args:  -XX:PermSize=10M -XX:MaxPermSize=10M
public class MethodAreaOOMTest {
    public static void main(String[] args) {
        while (true) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(MethodAreaOOMTest.class);
            enhancer.setUseCache(false);
            enhancer.setCallback(new MethodInterceptor() {
                public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                    return methodProxy.invokeSuper(o, objects);
                }
            });
            enhancer.create();
        }
    }
}
Copy after login

In the above code , we use CGlib to dynamically generate a large number of classes. Under JDK6, running the above code will generate an OutOfMemoryError: PermGen space exception:

/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home /bin/java -jar -XX:PermSize=10M -XX:MaxPermSize=10M target/Test-1.0-SNAPSHOT.jar
The output results are as follows:

Caused by: java.lang.OutOfMemoryError: PermGen space
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClassCond(ClassLoader.java:637)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:621)
        ... 11 more
Copy after login

MetaSpace memory overflow

In the section Memory Overflow in the Method Area, we mentioned that JDK8 does not have the concept of permanent generation, so the two examples did not achieve the expected results under JDK8. So under JDK8, whether Are there errors like memory overflow in the method area? Of course there are. In JDK8, the MetaSpace area is used to store Class-related information, so when the MetaSpace memory space is insufficient, java.lang.OutOfMemoryError: Metaspace will be thrown Exception.

We still take the example mentioned above as an example:

//VM Args: -XX:MaxMetaspaceSize=10M
public class MethodAreaOOMTest {
    public static void main(String[] args) {
        while (true) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(MethodAreaOOMTest.class);
            enhancer.setUseCache(false);
            enhancer.setCallback(new MethodInterceptor() {
                public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                    return methodProxy.invokeSuper(o, objects);
                }
            });
            enhancer.create();
        }
    }
}
Copy after login

The code part of this example has not been changed, the only difference is that we need to use JDK8 to run This code is set with the parameter -XX:MaxMetaspaceSize=10M. This parameter tells the JVM that the maximum size of Metaspace is 10M.

Then we use JDK8 to compile and run this example, and the following exception is output:

>>> java -jar -XX:MaxMetaspaceSize=10M target/Test-1.0-SNAPSHOT.jar
Exception in thread "main" java.lang.OutOfMemoryError: Metaspace
    at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:345)
    at net.sf.cglib.proxy.Enhancer.generate(Enhancer.java:492)
    at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:114)
    at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291)
    at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:480)
    at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:305)
    at com.test.MethodAreaOOMTest.main(MethodAreaOOMTest.java:22)
Copy after login

The above is the content of common Java memory overflow exceptions and code implementation. For more related content, please pay attention to the PHP Chinese website (www.php.cn)!




Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!