当前位置:编程学习 > JAVA >>

JVM学习笔记-内存溢出

JVM学习笔记-内存处理一文中已经介绍了JVM对内存区域的划分和处理。在实际编程过程中,会遇到一些OutOfMemory(OOM)异常。通过模拟。我们可以直接指出这些场景的本质,从而在纷繁复杂的千万行代码中避免这样去Coding。导致OOM的情况有多种,包括Java或Native Method Stack的内存不足或者栈空间溢出、Heap内存溢出、Non-heap内存溢出、Direct Memory溢出。


Java Method Stack栈溢出模拟
什么时候会让Java Method Stack栈溢出?栈的基本特点就是FILO(First In Last Out),如果in的太多而out的太少,就可能overflow了。而Java Method Statck的功能就是保存每一次函数调用时的“现场”,即为入栈,函数返回对应出栈,所以函数的调用深度越大,栈就变得越大,足够大的时候就会溢出。所以模拟Java Method Stack溢出,只要不断递归调用某一函数就可以导致溢出。
[java]
package com.jony.java; 
 
public class TestStackOverflow { 
    private int stackLength = 0; 
 
    public void stackOverFlow(){ 
        ++stackLength; 
        stackOverFlow(); 
    } 
 
    public static void main(String[] args){ 
        TestStackOverflow test = new TestStackOverflow(); 
        try { 
            test.stackOverFlow(); 
        } catch (Throwable e) { 
            System.out.println("Stack Length:" + test.stackLength); 
            e.printStackTrace(); 
        } 
    } 
 

package com.jony.java;

public class TestStackOverflow {
    private int stackLength = 0;

    public void stackOverFlow(){
        ++stackLength;
        stackOverFlow();
    }

    public static void main(String[] args){
        TestStackOverflow test = new TestStackOverflow();
        try {
            test.stackOverFlow();
        } catch (Throwable e) {
            System.out.println("Stack Length:" + test.stackLength);
            e.printStackTrace();
        }
    }

}
运行结果:
Stack Length:11477
java.lang.StackOverflowError
at com.jony.java.TestStackOverflow.stackOverFlow(TestStackOverflow.java:7)
at com.jony.java.TestStackOverflow.stackOverFlow(TestStackOverflow.java:8)
at com.jony.java.TestStackOverflow.stackOverFlow(TestStackOverflow.java:8)
at com.jony.java.TestStackOverflow.stackOverFlow(TestStackOverflow.java:8)
at com.jony.java.TestStackOverflow.stackOverFlow(TestStackOverflow.java:8)
at com.jony.java.TestStackOverflow.stackOverFlow(TestStackOverflow.java:8)
at com.jony.java.TestStackOverflow.stackOverFlow(TestStackOverflow.java:8)
at com.jony.java.TestStackOverflow.stackOverFlow(TestStackOverflow.java:8)
at com.jony.java.TestStackOverflow.stackOverFlow(TestStackOverflow.java:8)


        2.  Java Method Stack内存溢出模拟-Heap内存溢出
堆是用来存储对象的,当然对象不一定都存在堆里(栈上分配、标量替换技术)。那么堆如果溢出了,一定是不能被杀掉的对象太多了。模拟Heap内存溢出,只要不断的创建对象并保存对象引用存在即可。
[java]
package com.jony.java; 
 
import java.util.ArrayList; 
 
public class TestHeapOverflow { 
 
    static class TestOomHeap {} 
 
    public static void main(String[] args) { 
        ArrayList<TestOomHeap> list = new ArrayList<TestHeapOverflow.TestOomHeap>(); 
 
        while (true) { 
            list.add(new TestOomHeap()); 
        } 
    } 
 

package com.jony.java;

import java.util.ArrayList;

public class TestHeapOverflow {

    static class TestOomHeap {}

    public static void main(String[] args) {
        ArrayList<TestOomHeap> list = new ArrayList<TestHeapOverflow.TestOomHeap>();

        while (true) {
            list.add(new TestOomHeap());
        }
    }

}
运行结果:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.jony.java.TestHeapOverflow.main(TestHeapOverflow.java:13)


       3.  Method Area内存溢出

Method Area内存溢出,也就是Non-heap,是用来存储Object Class Data、变量、静态常量、JIT编译后的代码。如果该区域溢出,则说明某种数据创建的实在是太多了,模拟该异常,可以不断创建新的class,知道溢出为止。下面实例中会用到asm-all-3.0.jar和cglib2.2.jar 下载
[java]
package com.jony.java; 
 
import java.lang.reflect.Method; 
import net.sf.cglib.proxy.Enhancer; 
import net.sf.cglib.proxy.MethodInterceptor; 
import net.sf.cglib.proxy.MethodProxy; 
 
public class TestMethodAreaOverflow { 
 
    static class MethodAreaOom {} 
 
    public static void main(String[] args) { 
        while (true) { 
            Enhancer enhancer = new Enhancer(); 
            enhancer.setSuperclass(MethodAreaOom.class); 
            enhancer.setUseCache(false); 
            enhancer.setCallback(new MethodInterceptor() { 
                 
                @Override 
                public Object intercept(Object arg0, Method arg1, Object[] arg2, 
                        MethodProxy proxy) throws Throwable { 
                    return proxy.invoke(arg0, arg2); 
                } 
            }); 
         

补充:软件开发 , Java ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,