Java内存区域(虚拟机栈、本地方法栈、程序计数器、方法区、堆)
本篇文章是我对JVM进行学习的第一篇文章,主要是对java的内存区域有一个学习和认识,我们先来开一下JVM内存模型的一个概况图解:
接下来我们对于运行时数据区的五个内存区域做一个简单的介绍:
1.Java虚拟机栈
虚拟机栈描述的是Java方法执行的动态内存模型。当我们的栈空间不足时,就会抛出StackOverFlowError
- 栈帧:每一个方法执行都会创建一个栈帧,伴随着方法从创建到执行完成。用于存储局部变量表,操作数栈,动态链接,方法出口等信息
- 局部变量表:存放编译器可知的各种数据类型,引用类型,returnAddress类型。局部变量表的内存空间在编译器完成分配,当进入一个方法的时候,这个方法需要在帧中分配多少内存是固定的,方法运行期间是不会改变局部变量表的大小。
2.本地方法栈
- 虚拟机栈为虚拟机执行Java方法服务
- 本地方法栈为虚拟机栈执行native方法服务
3.堆内存
- 存放对象的实例
- 垃圾收集器管理的主要区域
- 新生代、老年代 Eden空间
4.方法区
- 存储虚拟机加载的类信息(类的版本、字段、方法、接口),常量,静态常量,即时编译器编译后的代码等数据
- 方法区和永久代:永久代的概念存在于HotSport虚拟机中,并非所有的方法去都被称为永久代。HotSport开发团队将GC 分代拓展到了方法区中,也就是说使用永久代来实现方法区,好处就是可以使用管理堆的代码来管理方法区的内存,剩去了为方法区专门编写一套内存管理的代码,因此说方法区和永久代并不等价,仅限于HotSport中
- 垃圾回收在方法去的行为:由于在方法区中进行垃圾回收的效率很低,很少进行垃圾回收,但是对于常量池和对象类型卸载还是会进行垃圾回收
- 异常的定义:OutOfMemeryError
5.程序计数器
- 程序计数器是一块较小的内存区域,是当前线程所执行的字节码文件的行号指示器
- 程序计数器处于线程独占区
- 如果线程执行的是Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址。如果执行的是native方法,这个计数器的值是undefined
- 此区域是唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError情况的区域