我门说一下,哪些区域可能发生OOM
我门一般将区域分为
程序计数器,每个线程内部的程序计数器
JAVA虚拟栈,Java栈,每个线程创建时候都创建一个虚拟机栈,保存一个个的栈帧
堆Heap Java内存管理的核心区域,放置Java对象实例,几乎所有创建Java对象都在堆上
方法区,所有线程共享的区域,存储所谓的元数据 对应的运行时常量池 字段 方法代码 类结构
运行时常量池,方法区一部分,放各种常量信息
本地方法栈,Java虚拟机栈类似,对本地方法的支持
那么我们这次是对于Java 6之后的变化进行的介绍
我们本次会说一下的广义上的JVM内存结果或者Java进程内存结构
可能出现OOM的内存区域
首先是关于内存结构图
我们在上面的图中标出
直接内存是指的Direct Buffer所分配的内存,虽然一般说其不是JVM 内存的一部分
JVM是一个本地程序,所以必然需要其他的内存去完成基本任务,JIT等,并将编译后的方法存储在Code Cache中
然后说明一些问题
Java对象的创建是不是在堆上,因为有着逃逸分析的概念,JVM会在栈上分配不会逃逸的对象,这样做其实取决于JVM设计者的选择
而且在Java 7之后,元数据区取代了永久代,所以Intern字符串分配直接在堆上了
然后是OOM出现的原因
首先是堆空间的不足,首先想的就是堆的大小不合理,没有显式的指定JVM堆或者数值偏小
对于Java虚拟机栈或者本地方法区,可能出现的是StackOverFlowError,当栈去试图扩展时候失败,也会出现OOM
对于老版本的JDK ,因为永久代的大小有限,且回收不积极,所以可能导致OOM,诸如的导致有Intern 字符串缓存占用太多空间
直接内存不足也会导致OOM