从几个sample来学习Java堆,方法区,Java栈和本地方法栈

转载 2013年12月05日 14:17:26

1)Java堆

所有对象的实例分配都在Java堆上分配内存,堆大小由-Xmx和-Xms来调节,sample如下所示:

[java] 
public class HeapOOM { 
     
    static class OOMObject{} 
 
    /**
     * @param args
     */ 
    public static void main(String[] args) { 
        List<OOMObject> list = new ArrayList<OOMObject>(); 
         
        while(true){ 
            list.add(new OOMObject()); 
        } 
    } 
 

加上JVM参数-verbose:gc -Xms10M -Xmx10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+HeapDumpOnOutOfMemoryError,就能很快报出OOM:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

并且能自动生成Dump。

2)方法区

方法区是存放虚拟机加载类的相关信息,如类、静态变量和常量,大小由-XX:PermSize和-XX:MaxPermSize来调节,类太多有可能撑爆永久带:

[java] 
public class MethodAreaOOM { 
     
    static class OOMOjbect{} 
 
    /**
     * @param args
     */ 
    public static void main(String[] args) { 
        // TODO Auto-generated method stub 
        while(true){ 
            Enhancer eh = new Enhancer(); 
            eh.setSuperclass(OOMOjbect.class); 
            eh.setUseCache(false); 
            eh.setCallback(new MethodInterceptor(){ 
 
                @Override 
                public Object intercept(Object arg0, Method arg1, 
                        Object[] arg2, MethodProxy arg3) throws Throwable { 
                    // TODO Auto-generated method stub 
                    return arg3.invokeSuper(arg0, arg2); 
                } 
                 
            }); 
            eh.create(); 
        } 
    } 
 

加上永久带的JVM参数:-XX:PermSize=10M -XX:MaxPermSize=10M,运行后会报如下异常:
Exception in thread "main" java.lang.OutOfMemoryError: PermGen space

静态变量或常量也会有可能撑爆方法区:

[java]
public class ConstantOOM { 
 
    /**
     * @param args
     */ 
    public static void main(String[] args) { 
        // TODO Auto-generated method stub 
        List<String> list = new ArrayList<String>(); 
        int i=0; 
        while(true){ 
            list.add(String.valueOf(i++).intern()); 
        } 
    } 
 

同样加上JVM参数:-XX:PermSize=10M -XX:MaxPermSize=10M,运行后报如下异常:
Exception in thread "main" java.lang.OutOfMemoryError: PermGen space

3)Java栈和本地方法栈

栈是存放线程调用方法时存储局部变量表,操作,方法出口等与方法执行相关的信息,栈大小由Xss来调节,方法调用层次太多会撑爆这个区域,samples如下所示:

[java] 
package com.cutesource; 
 
public class StackOOM { 
 
    /**
     * @param args
     */ 
     
    private int stackLength = 1; 
     
    public void stackLeak(){ 
        stackLength++; 
        stackLeak(); 
    } 
     
    public static void main(String[] args) throws Throwable{ 
        // TODO Auto-generated method stub 
        StackOOM oom = new StackOOM(); 
        try{ 
            oom.stackLeak(); 
        }catch(Throwable err){ 
            System.out.println("Stack length:" + oom.stackLength); 
            throw err; 
        } 
         
    } 
 

设置JVM参数:-Xss128k,报出异常:
Exception in thread "main" java.lang.StackOverflowError

打印出Stack length:1007,这里可以看出,在我的机器上128k的栈容量能承载深度为1007的方法调用。当然报这样的错很少见,一般只会出现无限循环的递归中,另外,线程太多也会占满栈区域:

[java]
package com.cutesource; 
 
public class StackOOM { 
 
    /**
     * @param args
     */ 
     
    private int stackLength = 1; 
     
    private void dontStop(){ 
        while(true){ 
            try{Thread.sleep(1000);}catch(Exception err){} 
        } 
    } 
     
    public void stackLeakByThread(){ 
        while(true){ 
            Thread t = new Thread(new Runnable(){ 
 
                @Override 
                public void run() { 
                    // TODO Auto-generated method stub 
                    dontStop(); 
                } 
                 
            }); 
            t.start(); 
            stackLength++; 
        } 
    } 
     
    public static void main(String[] args) throws Throwable{ 
        // TODO Auto-generated method stub 
        StackOOM oom = new StackOOM(); 
        try{ 
            oom.stackLeakByThread(); 
        }catch(Throwable err){ 
            System.out.println("Stack length:" + oom.stackLength); 
            throw err; 
        } 
         
    } 
 

报出异常:Exception in thread "main" java.lang.OutOfMemoryError:unable to create new native thread
不过在windows上运行这个例子要小心,会出现系统假死的情况,有可能需要重启机器才行。

以上几个例子虽然比较简单,但能很好帮助普通的程序员更加直观的了解Java堆,方法区,Java栈和本地方法栈。

相关文章推荐

从几个sample来学习Java堆,方法区,Java栈和本地方法栈

最近在看《深入理解Java虚拟机》,书中给了几个例子,比较好的说明了几种OOM(OutOfMemory)产生的过程,大部分的程序员在写程序时不会太关注Java运行时数据区域的结构:感觉有必要通过几个实...

学习Java堆,方法区,Java栈和本地方法栈

转载cutesource文章,只为学习,别无他意  http://blog.csdn.net/cutesource/article/details/8244250 《深入理解Java虚拟机》,书中给...

java虚拟机 jvm java堆 方法区 java栈

java堆是java应用程序最密切的内存空间。几乎所有的对象都存在堆中。java堆完全自动化管理,通过垃圾回收机制,垃圾对象会自动清理,不需要显式释放。 根据java垃圾回收机制的不同,java堆可能...

Java栈的实例-数组和链表两种方法

一、栈栈的定义 栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表。 (1)通常称插入、删除的这一端为栈顶 (Top),另一端称为栈底 (Bottom)。 ...

解析Java栈与堆

  • 2012年05月27日 15:12
  • 18KB
  • 下载

关于Java栈与堆的思考

  • 2007年04月20日 16:17
  • 33KB
  • 下载

Java栈与堆 的学习!转载!!

Java栈与堆   ----对这两个概念的不明好久,终于找到一篇好文,拿来共享   1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自...

java栈代码

  • 2011年12月23日 21:52
  • 1KB
  • 下载

JAVA栈类代码

  • 2014年09月25日 23:52
  • 806B
  • 下载

java栈和堆的区别

栈与堆都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。 Java的堆是一个运行时数据区,类的对象从中分配空间。这些对象通过new、n...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:从几个sample来学习Java堆,方法区,Java栈和本地方法栈
举报原因:
原因补充:

(最多只允许输入30个字)