【JVM虚拟机】关于Java内存区域与内存溢出异常小记
这一阵子阅读了《深入理解Java虚拟机》第二章,写的真的很好,所以决定记录下来,以后没事翻翻博客看看。????
Java虚拟机在运行java代码时,将内存区域分为
1.程序计数器
该区域是线程私有,字节码解释器工作时,就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,例如:循环,跳转,异常处理,线程恢复等基础功能。该内存区域是唯一一个在jvm里面没有规定任何OOM情况的区域
2.java虚拟机栈
该区域线程私有,生命周期与线程相同,java每个方法执行的时候都会创建一个栈桢用于存放局部变量表、操作栈桢、动态链接、方法出口等信息。每个方法从调用到执行完成都对应一个栈桢从虚拟机栈中入栈到出栈过程。其中局部变量表存放了编译期可知的基本数据类型(boolean,byte,char,short,int,float,long,double)、对象引用类型。抛出异常为StackOverFlow和OOM。
3.本地方法栈
该区域线程私有,与虚拟机栈发挥的作用十分相似。区别为虚拟机栈为虚拟机执行java方法服务,而本地方法栈则为虚拟机使用的Native方法服务。本地方法栈也会抛出StackOverFlow和OOM。
4.java堆
该区域线程共享,java堆是java虚拟机所管理的内存中最大的一块,虚拟机启动时创建,用于存放对象实例,所有对象实例以及数组都要在堆上分配。且是垃圾收集器管理的主要区域。java堆还可以细分为新生代和老年代,用于进行不同的垃圾收集算法GC。当前的主流虚拟机可以扩展,通过-Xmx和-Xms控制。如果堆没法再扩展内存时,将会抛出OOM异常。
5.方法区
该区域线程共享,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。java虚拟机规范把方法去描述为堆的一个逻辑部分。抛出异常类型为OOM。
6.运行时的常量池
这是方法区的一部分。用于存放编译器生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。运行时常量池相对于Class文件常量池的另外一个重要特性是具备动态性,Java语言并不要求常量一定只有编译器才能产生,也就是并非预置入Class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中,比较常见的就是String类的intern()方法。抛出异常类型为OOM。
下面这张图是对象的访问定位
通过这张图我们就能清楚的知道,发生的内存溢出,是哪一块儿出来的,而我也会贴上书上写的代码,并分析这种溢出情况。
1.java堆溢出代码
emm 过几天再贴吧,写了好长时间加上组织语言,有点累。