JVM內存溢出示例

1Java 堆溢出

下面的程中我們限制Java 堆的大小爲20MB,不可擴展(將堆的最小值-Xms 

數與最大值-Xmx 參數設置爲一樣即可避免堆自動擴展),通過參數-XX:+HeapDump

OnOutOfMemoryError 可以讓虛擬機在出現內存溢出異常時Dump 出當前的內存堆轉儲

快照以便事後進行分析。

參數設置如下




package com.yhj.jvm.memory.heap;

 

import java.util.ArrayList;

import java.util.List;

 

/**

 * @Described:堆溢出測試

 * @VM args:-verbose:gc -Xms20M -Xmx20M -XX:+PrintGCDetails

 * @author YHJ create at 2011-11-12 下午07:52:22

 * @FileNmae com.yhj.jvm.memory.heap.HeapOutOfMemory.java

 */

public class HeapOutOfMemory {

 

    /**

     * @param args

     * @Author YHJ create at 2011-11-12 下午07:52:18

     */

    public static void main(String[] args) {

       List<TestCase> cases = new ArrayList<TestCase>();

       while(true){

           cases.add(new TestCase());

       }

 

    }

 

}

/**

 * @Described:測試用例

 * @author YHJ create at 2011-11-12 下午07:55:50

 * @FileNmae com.yhj.jvm.memory.heap.HeapOutOfMemory.java

 */

class TestCase{

   

}


ava 堆內存的OutOfMemoryError異常是實際應用中最常見的內存溢出異常情況。出現Java 堆內

存溢出時,異常堆棧信息“java.lang.OutOfMemoryError”會跟着進一步提示“Java heap

space”

要解決這個區域的異常,一般的手段是首先通過內存映像分析工具(如Eclipse

Memory Analyzer)對dump 出來的堆轉儲快照進行分析,重點是確認內存中的對象是

否是必要的,也就是要先分清楚到底是出現了內存泄漏(Memory Leak)還是內存溢

出(Memory Overflow)。圖2-5 顯示了使用Eclipse Memory Analyzer 打開的堆轉儲快

照文件。

如果是內存泄漏,可進一步通過工具查看泄漏對象到GC Roots 的引用鏈。於是就

能找到泄漏對象是通過怎樣的路徑與GC Roots 相關聯並導致垃圾收集器無法自動回收

它們的。掌握了泄漏對象的類型信息,以及GC Roots 引用鏈的信息,就可以比較準確

地定位出泄漏代碼的位置。

如果不存在泄漏,換句話說就是內存中的對象確實都還必須存活着,那就應當檢查

虛擬機的堆參數(-Xmx -Xms),與機器物理內存對比看是否還可以調大,從代碼上

檢查是否存在某些對象生命週期過長、持有狀態時間過長的情況,嘗試減少程序運行期

的內存消耗。

以上是處理Java 堆內存問題的簡略思路,處理這些問題所需要的知識、工具與經驗

在後面的幾次分享中我會做一些額外的分析。

2java棧溢出

package com.yhj.jvm.memory.stack;

/**

 * @Described:棧層級不足探究

 * @VM args:-Xss128k

 * @author YHJ create at 2011-11-12 下午08:19:28

 * @FileNmae com.yhj.jvm.memory.stack.StackOverFlow.java

 */

public class StackOverFlow {

   

   

    private int i ;

   

    public void plus() {

       i++;

       plus();

    }

 

    /**

     * @param args

     * @Author YHJ create at 2011-11-12 下午08:19:21

     */

    public static void main(String[] args) {

       StackOverFlow stackOverFlow = new StackOverFlow();

       try {

           stackOverFlow.plus();

       } catch (Exception e) {

           System.out.println("Exception:stack length:"+stackOverFlow.i);

           e.printStackTrace();

       } catch (Error e) {

           System.out.println("Error:stack length:"+stackOverFlow.i);

           e.printStackTrace();

       }

 

    }

 

}

3、常量池溢出(常量池都有哪些信息,我們在後續的JVM類文件結構中詳細描述)

 

package com.yhj.jvm.memory.constant;

 

import java.util.ArrayList;

import java.util.List;

 

/**

 * @Described:常量池內存溢出探究

 * @VM args : -XX:PermSize=10M -XX:MaxPermSize=10M

 * @author YHJ create at 2011-10-30 下午04:28:30

 * @FileNmae com.yhj.jvm.memory.constant.ConstantOutOfMemory.java

 */

public class ConstantOutOfMemory {

 

    /**

     * @param args

     * @throws Exception

     * @Author YHJ create at 2011-10-30 下午04:28:25

     */

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

       try {

           List<String> strings = new ArrayList<String>();

           int i = 0;

           while(true){

              strings.add(String.valueOf(i++).intern());

           }

       } catch (Exception e) {

           e.printStackTrace();

           throw e;

       }

 

    }

 

}

4、方法去溢出

package com.yhj.jvm.memory.methodArea;

 

import java.lang.reflect.Method;

 

import net.sf.cglib.proxy.Enhancer;

import net.sf.cglib.proxy.MethodInterceptor;

import net.sf.cglib.proxy.MethodProxy;

 

/**

 * @Described:方法區溢出測試

 * 使用技術 CBlib

 * @VM args : -XX:PermSize=10M -XX:MaxPermSize=10M

 * @author YHJ create at 2011-11-12 下午08:47:55

 * @FileNmae com.yhj.jvm.memory.methodArea.MethodAreaOutOfMemory.java

 */

public class MethodAreaOutOfMemory {

 

    /**

     * @param args

     * @Author YHJ create at 2011-11-12 下午08:47:51

     */

    public static void main(String[] args) {

       while(true){

           Enhancer enhancer = new Enhancer();

           enhancer.setSuperclass(TestCase.class);

           enhancer.setUseCache(false);

           enhancer.setCallback(new MethodInterceptor() {

              @Override

              public Object intercept(Object arg0, Method arg1, Object[] arg2,

                     MethodProxy arg3) throws Throwable {

                  return arg3.invokeSuper(arg0, arg2);

              }

           });

           enhancer.create();

       }

    }

 

}

/**

 * @Described:測試用例

 * @author YHJ create at 2011-11-12 下午08:53:09

 * @FileNmae com.yhj.jvm.memory.methodArea.MethodAreaOutOfMemory.java

 */

class TestCase{

   

}

5、直接內存溢出

package com.yhj.jvm.memory.directoryMemory;

 

import java.lang.reflect.Field;

 

import sun.misc.Unsafe;

 

/**

 * @Described:直接內存溢出測試

 * @VM args: -Xmx20M -XX:MaxDirectMemorySize=10M

 * @author YHJ create at 2011-11-12 下午09:06:10

 * @FileNmae com.yhj.jvm.memory.directoryMemory.DirectoryMemoryOutOfmemory.java

 */

public class DirectoryMemoryOutOfmemory {

 

    private static final int ONE_MB = 1024*1024;

    private static int count = 1;

 

    /**

     * @param args

     * @Author YHJ create at 2011-11-12 下午09:05:54

     */

    public static void main(String[] args) {

       try {

           Field field = Unsafe.class.getDeclaredField("theUnsafe");

           field.setAccessible(true);

           Unsafe unsafe = (Unsafe) field.get(null);

           while (true) {

              unsafe.allocateMemory(ONE_MB);

              count++;

           }

       } catch (Exception e) {

           System.out.println("Exception:instance created "+count);

           e.printStackTrace();

       } catch (Error e) {

           System.out.println("Error:instance created "+count);

           e.printStackTrace();

       }

 

    }

 

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章