所有的java代码无非分三种类型(数据,控制,指令),如下图所示

程序计数器【指令类型】
因为线程的执行是通过cpu的,在线程执行指令的过程中,cpu可能被抢占,而需要有个地方记录指令执行到哪里了,所以需要程序计数器
- 每个线程都有一个单独的程序计数器
- 执行JAVA方法时,计数器记录正在执行的.class文件字节码行号,
- 如果执行的是native方法,则计数器为空
- 内存占用比较小,划分在CPU上,程序无法直接操作
- 如果执行的不是Java方法,而是本地方法NativeMethod,这个计数器值为空(Undefined)
- 这是JVM 规范的唯一没有OutMemoryError的内存区域
JVM虚拟机栈【指令类型】
用于存储当前线程运行方法所需要的数据,指令,返回地址,特点如下:
- 每个方法执行时产生一个栈帧,方法的执行就是栈针在JVM中出栈入栈的过程
- 内存的分配和释放速度快
- JAVA编译器必须知道存储在堆栈内所有数据的确切大小和生命周期,不灵活
- 栈的大小所需内存在编译时期完成分配,方法运行时期不改变局部变量表大小,四个字节占用一个局部变量空间
- 栈的大小决定了方法调用的可达深度(递归多少层次,或嵌套调用多少层其他方法,-Xss参数可以设置虚拟机栈大小)
虚拟机栈存储的主要组成部分如下
- 局部变量表:用于存储方法中的变量(基本类型的值-和-引用类型的地址)
- 操作数栈:用于存储操作(通过压栈和弹栈的方式)
- 动态连接:例子(controller方法中用到service,当执行的时候,解析具体使用的service实例)就是动态连接
- 返回值:包括,方法正常结束时的返回地址,和异常时的处理方法

本地方法区【指令类型】
和虚拟机栈功能相似,但管理的不是JAVA方法,是本地方法,本地方法是用C实现的
方法区
存储类的信息,常量(jdk1.7),静态变量,JIT
- 存储类JVM已加载的Class元数据包括类和接口的全限定名,字段,方法的名称和描述
- 存储常量、静态变量: (基本类型如int,Integer,long等,无小数布尔),(对象类型如String,数组等)
- 常量池:常量池数据编译期被确定,并且在持久带,线程共享,是Class文件中的一部分。存储了类、方法、接口等中的常量,当然也包括字符串常量。
- 字符串常量池:是常量池中的一部分,存储编译期类中产生的字符串类型数据。(JDK1.7开始已经移动至堆中)
- 运行时常量池:方法区的一部分,所有线程共享。虚拟机加载Class后把常量池中的数据放入到运行时常量池。
JVM堆
存储对象和数据共线程共享(优化重点,垃圾回收重点)
- Java堆可以处于物理上不连续的内存空间中,只要逻辑连续即可
- 在虚拟机启动时创建,可通过-Xmx和-Xms控制大小
- 分为新生代和老年代
网友评论