java内存区域与内存溢出异常
运行时数据区
程序计数器/PC寄存器
- 当前线程所执行的字节码的行号指示器
- 每条线程都是独立的,独立存储,线程私有内存
- 当线程执行一个java方法时,记录正在执行的虚拟机字节码指令地址. 若为native方法,则为空
- 唯一一个java虚拟机中没有规定OOM情况的区域
虚拟机栈/方法栈
-
每个方法在执行时都会创建一个栈帧用于存放局部变量表,操作数栈,动态链接,方法出口等信息.每一个方法从调用到完成对应这一个栈帧在虚拟机中的入栈到出栈
- 局部变量表:存放编译期可知的基本类型,对象的引用(引用指针,对象句柄或其它与对象相关的位置信息 非对象本身),returnAddress类型(指向了一条字节码指令的地址)
64位(long,double)会占用2个局部变量空间(slot),其余占用一个
在方法运行时不会改变大小
- 线程私有的,生命周期与线程保持一致
- 常说的栈内存指的就是虚拟机栈
- 异常信息:
StackOverFlowError:线程请求的栈深度大于虚拟机允许的栈深度
OutOfMemoryError:虚拟机可动态扩展,但扩展时无法申请到足够内存
本地方法栈
-
与虚拟机栈基本一致
区别:
仅保存Native方法信息
java堆/GC堆
-
存放对象实例
-
被所有线程共享,虚拟机启动时创建
- 共享总大小内存,对于每一个线程可能划分出私有的分配缓冲区
-
垃圾管理器主要区域,所以也被称为GC堆
- 因此分出年轻代(eden,survivor),老年代(old) 1:1:8
-
-Xms -Xmx
-
OOM
方法区(Non-Heap)
-
用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码
-
所有线程共享
-
在HotSpot也被称为永久代
- 在JDK1.7版本的HotSpot中已将放在永久代的字符串常量池移出
-
方法区可以不实现垃圾收集
-
OOM
运行时常量池
-
方法区 的一部分
-
用于存放编译期生成的字面量,符号引用,直接引用,当类加载完毕后加入
-
具备动态性,运行期间也可将新的常量放入池中, String.intern()
-
String.intern()
- jDK1.6 会将实例复制到永久代,并返回这个复制的引用
- JDK1.7 不在复制实例,仅在常量池中记录首次出现的实例引用
- String str = "java";
String str2 = new String("java");
boolean flag = str == str2 ;
flag 是false
new String() 创建一个对象并在堆上,str2保存堆对象地址
"java“str保存的是常量池中的java地址;
-
-
OOM
直接内存
- 不属于运行时数据区,也不是java虚拟机规范中定义的内存区域
- OOM
对象
对象的创建
-
1.类加载检查. 先查询参数是否在常量池中有一个类的符号引用, 检查这个符号引用代表的类是否已经被加载,解析 初始化过,如果没有 ,则需要进行相应的类加载过程
-
- 虚拟机分配内存,并初始化为0(不包含对象头)
-
3.虚拟机对对象进行必要设置,实例信息,元数据信息,对象hash码,GC分代信息等,这些信息在对象头中
-
执行init方法 代码:P45
对象的内存布局
-
对象头
-
实例数据
- 存储对象的有效信息,定义的字段内容,受到java编写顺序和虚拟机分配策略参数影响
-
对齐填充
- 非必然存在,仅仅是占位符的作用
对象的访问定位
-
通过栈中的reference数据来操作堆中的具体对象
-
直接指针 reference 中直接保存对象地址
SUN HotSpot 采用直接指针
- 实例数据
- 类型数据指针
-
使用句柄 reference中保存句柄地址
-
在堆中维护一个句柄池
- 实例数据指针
- 类型数据指针
-
-
OOM
参数设置: -verbose:gc -Xms20M -Xmx20m -Xmn10m -XX:+PrintGCDetails -XX:SurvivorRatio=8
-
java堆溢出
-
java heap space 会有dump文件 ,通过分析dump文件确定是溢出还是泄漏
- 泄漏: 查看GC roots 的引用链定位泄漏代码
- 溢出:调整物理机内存大小,查看对象的生命周期是否过长,持有状态过长, 减少程序运行期间的内存消耗
-
-
虚拟机栈和本地方法栈溢出
-
方法区和运行时常量池溢出
- 动态生成大量的class时有可能发生,常见的有:动态生成大量JSP文件,基于OSGi的应用
-
本机直接内存溢出
- 通过-XX: MaxDirectMemorySize指定,默认与堆最大值一致(-Xmx)
- Heap Dump 文件中不会看见明显的异常,若OOM后Dump文件很小,程序中直接或间接使用了NIO则可能出现
高清思维导图版请关注公众号‘伊人网络’ 回复 ‘内存’ 即可领取
原文
http://www.cnblogs.com/diandiandian/p/13192369.html
本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » java内存区域与内存溢出异常