java虚拟机运行时数据区域

时间:2022-12-27 20:08:43

java内存区域与内存溢出异常

运行时数据区域

方法区和堆是所有线程共享的区域
其他的是线程隔离的区域
java虚拟机运行时数据区域
1.程序计数器:线程私有,记录java虚拟机执行指令的位置。是唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError情况的区域,因为它是一个整数,所占有的空间大小是可预见的,所以没必要规定!
2.java虚拟机栈:线程私有,描述的是java方法在内存中执行模型。java虚拟机栈的内存大小是程序启动时可以自己主动设置的,java中每个方法被调用的时候都会创建一个栈帧,然后被压入到栈中,java程序执行的过程其实就是栈帧入栈和出栈的过程。栈帧包括几个部分:局部变量表,操作数栈,动态链接,方法返回地址。

  • 局部变量表:
    • 存放编译期可知的各种基本数据类型、对象引用类型和returnAddress类型(指向一条字节码指令的地址:函数返回地址)。
    • long、double占用两个局部变量控件Slot。
    • 局部变量表所需的内存空间在编译期确定,当进入一个方法时,方法在栈帧中所需要分配的局部变量控件是完全确定的,不可动态改变大小。
    • 异常:线程请求的栈帧深度大于虚拟机所允许的深度—*Error,如果虚拟机栈可以动态扩展(大部分虚拟机允许动态扩展,也可以设置固定大小的虚拟机栈),但是无法申请到足够的内存—OutOfMemorError。

  • 操作数栈:

    • 后进先出LIFO,最大深度由编译期确定。栈帧刚建立使,操作数栈为空,执行方法操作时,操作数栈用于存放JVM从局部变量表复制的常量或者变量,提供提取,及结果入栈,也用于存放调用方法需要的参数及接受方法返回的结果。
    • 操作数栈可以存放一个jvm中定义的任意数据类型的值。
    • 在任意时刻,操作数栈都一个固定的栈深度,基本类型除了long、double占用两个深度,其它占用一个深度

  • 动态连接:

          每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接。Class文件的常量池中存在有大量的符号引用,字节码中的方法调用指令就以常量池中指向方法的符号引用为参数。这些符号引用,一部分会在类加载阶段或第一次使用的时候转化为直接引用(如final、static域等),称为静态解析,另一部分将在每一次的运行期间转化为直接引用,这部分称为动态连接。


3.本地方法栈:线程私有,本地方法栈和java虚拟机栈类似,只是java虚拟机栈是服务于java虚拟机执行java方法,而本地方法栈是服务于java虚拟机执行native方法。本地方法栈和java虚拟机栈一样都会跑出*Error和OutOfMemoryError异常。
4.堆:线程共享,存放几乎所有的对象实例,也是GC重点管理的地方,故被称为GC堆。堆分为几个区域:Eden空间,Survivor空间,from,to。
5.方法区:线程共享,又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量
6、运行时常量池和直接内存