JVM研究(1)内存溢出试验

  本文是在JDK1.7下面做的试验,通过模拟,我们可以直接点中这些场景的本质,从而在纷繁复杂的千万行代码中避免这样去 coding。导致 OOM 的情况有多种,包括 Java 或 Native Method Stack 的内存不足或者栈空间溢出(stack over Flow)、Heap 内存溢出(OOM)、Non-heap 内存溢出(OOM)、Direct Memory 溢出。

  1.java 方法栈溢出

  什么时候会让 Java Method Stack 栈溢出啊?栈的基本特点就是 FILO(First In Last Out),如果 in 的太多而 out 的太少,就好 overflow 了。而 Java Method Stack 的功能就是保存每一次函数调用时的“现场”,即为入栈,函数返回就对应着出栈,所以函数调用的深度越大,栈就变得越大,足够大的时候就会溢出。所以模拟 Java Method Stack 溢出,只要不断递归调用某一函数就可以。

package com.elong.ihotel.util;
/**
 * 测试栈溢出的情况
 * @author user
 *
 */
public class TestStackOverFlow implements Runnable {

    private int stackLength = 0;

    @Override
    public void run() {
        this.stackOverFlow();
    }

    /**
     * 递归的调用
     */
    public void stackOverFlow() {
        ++stackLength;
        stackOverFlow();
    }

    public static void main(String[] args) throws InterruptedException {
        
        
        TestStackOverFlow r = new TestStackOverFlow();
        
        try {
            //创建一个线程
            Thread t = new Thread(r);
            Thread.sleep(20000);
            System.out.println("线程执行开始------"+t.getName());
            //线程启动
            t.start();
            Thread.sleep(10000);
            System.out.println("线程执行结束------"+t.getName());
        } catch (Exception e) {
            throw e;
        }finally{
            System.out.println("栈的长度"+r.stackLength);
        }

    }

}

运行结果:

  

     

使用JAVA - VisualVM观察如下:

  2.java heap space 溢出

   堆是用来存储对象的,当然对象不一定都存在堆里(由于逃逸技术的发展)。那么堆如果溢出了,一定是不能被杀掉的对象太多了。模拟 Heap 内存溢出,只要不断创建对象并保持有引用存在即可。

package com.elong.ihotel.util;

import java.util.ArrayList;
import java.util.List;

/**
 * 测试栈溢出的情况
 * @author user
 *
 */
public class TestheapOOM implements Runnable {

    private static class HeapOomObject {
    }

    @Override
    public void run() {
        List<HeapOomObject> list = new ArrayList<HeapOomObject>();
        while (true) {
           list.add(new HeapOomObject());
        }
    }


    public static void main(String[] args) throws InterruptedException {

        TestheapOOM r = new TestheapOOM();

        try {
            // 创建一个线程
            Thread t = new Thread(r);
            Thread.sleep(20000);
            System.out.println("线程执行开始------" + t.getName());
            // 线程启动
            t.start();
            Thread.sleep(10000);
            System.out.println("线程执行结束------" + t.getName());
        } catch (Exception e) {
            throw e;
        } 
    }

}

运行结果:

  

 

使用jstat命令观察结果:结果一直在FGC,最终老年代O区内存使用情况达到98.08%,垃圾回收不了,最终导致OOM。

你可能感兴趣的:(JVM研究(1)内存溢出试验)