目录
运行时数据区域概要
关于运行时数据区域,可由两方面来划分:
1. 所有线程共享
1.1 方法区
用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。
运行时常量池:class文件中除了有类的版本,字段、方法、接口等描述信息外,还有一项信息是常量池表,用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。
1.2 堆
虚拟机中内存管理最大的一块,用来存放所有的对象实例。
1.3 执行引擎
虚拟机自主实现的字节码解析操作,有编译执行和解释执行组合完成。
1.4 本地库接口
是一个编程框架使得运行在Java虚拟机上的Java程序调用或者被调用特定于本机硬件与操作系统的用其它语言(C、C++或汇编语言等)编写的程序。
当出现仅用Java语言无法胜任的工作或者需要调用其它语言实现的场景时,可通过该接口调用平滑接入。该接口并不会在jvm中运行,故占用的是物理机的资源。
2.单线程独享
2.1 虚拟机栈
虚拟机栈是描述的是java方法执行的线程内存模型:每个方法执行的时候,虚拟机都会同步创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机中从入栈到出栈的过程。
栈帧:是jvm进行方法调用的使用的数据存储结构,虚拟机栈由多个栈帧组成;
操作数栈:指的是方法内变量动态运算后的数据,保存运算过程中的中间结果,是一种临时的变量存储空间;
动态链接:Class 文件中存放了大量的符号引用,字节码中的方法调用指令就是以常量池中指向方法的符号引用作为参数。这些符号引用一部分会在类加载阶段或第一次使用时转化为直接引用,这种转化称为静态解析。另一部分将在每一次运行期间转化为直接引用,这部分称为动态连接。
方法出口:当一个方法执行的时候,只有两种可以退出方法的方法。第一种是JVM碰到任意一个方法返回的字节码指令,被称为正常完成出口。另一种是在执行方法中抛出异常并且未对异常进行处理,被称为异常完成出口。方法退出的时候相当于把栈帧出栈。
2.2 本地方法栈
本地方法栈与虚拟机栈所发挥的作用是非常相似的,其区别只是虚拟机栈为虚拟机执行java方法服务,而本地方法栈则是为虚拟机使用到的本地方法服务。
2.3 程序计数器
程序计数器是一块较小的内存空间,可看作是当前线程执行的字节码的行号指示器;
它的主要作用是用来记录当前线程执行代码的字节码指令,也就是代码的行号,字节码解释器工作时就是通过改变这个计数器的值,来选取下一条要执行的字节码指令;那么,为什么要记录每个线程的行号呢,试想一下,我们java虚拟机的多线程是通过cpu轮流切换的方式实现的,在任意一个时刻,一个处理器就只会执行一条线程中的指令,所以在不同线程之间切换的时候,我们需要知道当前线程执行代码的位置,来恢复线程的正常执行流程,故各个线程之间需要独立存储该内存区域;