Java 出现内存溢出的定位以及解决方式

1.Java虚拟机栈与本地方法栈

栈的大小控制参数时 -Xss。

Java虚拟机在栈中定义了两种异常,StrackOverFlowError和OutOfMemeryError。当请求栈的深度大于java虚拟机所允许的最大深度则抛出StrackOverFlowError;如果Java虚拟机在栈扩展时,没有申请到足够的空间时,则抛出OutOfMemeryError。

StrackOverFlowError:Java虚拟机在运行中,调用方法时,都要创建栈帧,当栈的空间不够时就会产生StrackOverFlowError。那么对应的解决方法就只能是调节-Xss参数,或者减少方法的调用,减小栈帧的大小两种方式。

OutOfMemeryError:在栈上出现OOM一般是多线程的情形。首先咋们解析一下栈使用的空间可以有多大,拿32位操作系统来举例, 最大内存2G – Xmx(最大堆容量)- MaxPermSize(最大方法区容量)- 虚拟机本身耗费的内存和程序计数器使用的内存。 剩下的内存就是栈可以使用的空间,当Xss配置的参数一定时,那么在不断的创建线程过程中,遇到不能申请到栈空间的时候就会抛出OOM,那么对应的解决方式就是,调节-Xss参数降低栈大小,或者调节-Xmx以及MaxPermSize的大小扩大留给栈的空间。

2.方法区内存溢出

方法区的大小通过-PermSize和-MaxPermSize控制。

因为类常量和运行时常量也存储在方法区中,所以运行时常量过多也可导致方法区的OOM,但是没有直接控制常量池大小的参数,只能通过-PermSize和-MaxPermSize来间接控制。

在Spring以及Hibernate,Mybatis中都会使用GeneratedConstructorAccessor、动态代理以及CGLib字节码增强技术的等动态生成类,那么就需要强大的方法区来支撑。

3.堆内存的溢出

堆内存的溢出比较复杂,需要调节GC等多种参数,我们在后面的章节中会进行讲解。

标签