Java虚拟机内存结构
时间:20170227
Java与C++之间有一堵有内存动态分配和垃圾收集技术所围成的“高墙”,墙外面的人想进来,墙里面的人却想出去。
线程:顺序执行单元。
一、运行时数据区
java运行时数据区图如下:
1线程独占区
1.1.程序计数器
是一块较小的内存空间,记录当前线程所执行的字节码行号。
1.2.java虚拟机栈
存放方法运行时所需的数据。
虚拟机栈:为虚拟机执行Java方法服务。
虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机中入栈到出栈的过程。
同程序计数器一样,java虚拟机栈也是线程独占的。他的生命周期与线程相同。
-
栈帧
- 每个方法执行,都会创建一个栈帧,伴随着方法从创建到执行完成。用于存储局部变量表,操作数栈、动态链接、方法出口等。
-
局部变量表
- 用于存放编译器可知的各种基本数据类型,引用类型、returnAddress类型。
- 局部变量表的内存空间在编译期完成分配,当进入一个方法时,这个方法需要在栈帧中分配多少内存时固定的,在方法运行期间时不会改变局部变量表的大小的。
-
虚拟机栈大小及栈帧大小
- StackOverflowError产生的原因分析:由于每个方法在执行的过程中都会在虚拟机栈中创建一个栈帧,当出现循环调用时(例如A方法不停的调用自身),就会不停的生成栈帧,并压入虚拟机栈中,直到超过栈的大小,抛出错误。StackOverflowError。
- OutOfMemory:为上述情况极端情形。
1.3.本地方法栈
为JVM所调用的Native方法服务。
本地方法栈与虚拟机栈的作用相似。
虚拟机栈:为虚拟机执行Java方法服务。
本地方法栈:为JVM所调用的Native方法服务。
2线程独占区
2.1 方法区
存储运行时常量池,已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
方法区与java堆一样是各个线程共享的内存区域。
- 类信息:包括类的版本、字段、方法、接口
2.2 java堆
存储对象实例
java堆是被所有线程所共享的一块内存区域,在虚拟机启动时创建。在内存区域的唯一目的就是存放对象的实例,几乎所有的对象实例都在这里分配内存。
对于大多数应用来说,java堆是java虚拟机管理的内存中最大的一块。因为在java应用中会不停的创建java对象。只要时对象的存储都会放在堆中。
java堆也是垃圾收集器管理的主要区域。很多时候被成为GC堆(Garbage Collected Heap),也称为垃圾堆。
Java堆还可以细分为:新生代和老年代。
2.3运行时常量池
运行时常量池(Runtime Constant Pool)是方法区的一部分。class文件中除了有类的版本、字段、方法、接口以外,还有一项信息是常量池(Constant Pool Table),用于存放编译期生成的各种字面量和符号引用,这部分类容将在类加载后进入方法区的运行时常量池中存放。
2.4直接内存
直接内存并不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域。