JVM架构(013)_java什么情况会内存溢出

转载 2016年08月29日 17:15:22

1、Java堆什么情况会溢出

所有对象的实例都在Java堆上分配内存,堆大小由-Xmx和-Xms来调节,如果程序使用的内存超过了堆最大内存(-Xmx),则会溢出Java heap space

了解java内存模型看这里:java内存模型是什么样的 
了解堆内存看这里:java堆内存是什么样的 
了解java垃圾回收机制看这里: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

其中-verbose:gc是为了打印GC过程的详细情况,上述程序就能很快报出内存溢出(OOM): 
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space

并且能自动生成Dump文件,Dump记录了进程内存的完整信息。

了解Dump文件看这里:什么是Dump文件

2、Java方法区什么情况会溢出

方法区(永久代)是存放虚拟机加载类的相关信息(如类、静态变量和常量),大小由-XX:PermSize和-XX:MaxPermSize来调节,类太多有可能使永久代溢出PermGen space。Java 8 以后移除了方法区,取而代之的是本地元空间Metaspace,大小由-XX:MetaspaceSize和-XX:MaxMetaspaceSize调节,移除的错误也变为java.lang.OutOfMemoryError: Metaspace。

实例:

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

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

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来调节,方法调用层次太多会使栈溢出StackOverflowError

实例:

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的方法调用。当然这个错误很少见,一般只会出现无限循环的递归中,另外,线程太多也会占满栈区域(线程内分配了自己的栈,但是进程中所有线程可使用的栈总大小是一定的):

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在什么情况下会内存溢出?

个人觉得,由于有GC,大多数情况下,不会出现。但是,如果某些资源没有关闭(例如I/O文件和数据库连接没有关闭),就有可能出现 out of Memory的情况。 以上,只是个人的经验作出的结论。 ...

java有内存溢出吗?如果有是什么情况?

java有内存溢出吗?如果有是什么情况? 内存溢出是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于虚拟机能提供的最大内存。 所以我们应该...
  • cynhafa
  • cynhafa
  • 2011年09月19日 17:16
  • 1058

什么情况下会导致内存泄露

什么情况下会导致内存泄漏
  • caialun
  • caialun
  • 2017年01月05日 11:17
  • 481

谈谈什么情况下会导致内存泄露

Android 的虚拟机是基于寄存器的 Dalvik,它的最大堆大小一般是 16M,有的机器为 24M。因此我们所能利用的内存空间是有限的。如果我们的内存占用超过了一定的水平就会出现 OutOfMem...

Android中什么情况下会导致内存泄露

Android 的虚拟机是基于寄存器的Dalvik,它的最大堆大小一般是16M,有的机器为24M。因此我们所能利用的内存空间是有限的。如果我们的内存占用超过了一定的水平就会出现OutOfMemory ...

菱形继承的内存布局是怎么回事呢?访问时,又会出现什么情况?

首先,我们看一下菱形继承(也叫钻石继承)的类之间的关系,如下图: 这样的话,那D类有两个B类成员吗?,访问的话岂不是两个同名吗?那我们验证一下, 用代码表示的话就是://菱形继承 #inclu...

什么情况下会导致内存泄漏

转载地址 :http://blog.csdn.net/mwq384807683/article/details/70313673 一.资源释放问题: 程序代码的问题,长期保持某些资源,如C...

什么情况下会导致内存泄露

什么情况下会导致内存泄露 Android的虚拟机是基于寄存器的Dalvik,它的最大堆大小一般是16M,有的机器为24M。因此我们所能利用的内存空间是有限的。 如果我们的内存占用超过了一定的水平就会出...

深入理解JVM02--Java 内存溢出(java.lang.OutOfMemoryError)的常见情况和处理方式总结

1、Java堆溢出     Java堆用于存储对象实例,只要不断地创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,那么在对象数量到达最大堆的容量限制后就会产生内存...

使用Java自带的VisualVM监控远程主机JVM内存使用情况

下面是使用JXM协议配置的简单的操作步骤,详细内容可以阅读文章后的参考资料。 1.远程主机 (1)修改JMX服务的配置文件:   在JDK的根目录/jre/lib/management中,将...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:JVM架构(013)_java什么情况会内存溢出
举报原因:
原因补充:

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