文章目录运行时的数据区域一.程序计数器二.Java虚拟机栈局部变量表:操作数栈三.本地方法栈四.Java堆五.方法区(非堆)运行时常量池直接内存运行时的数据区域一.程序计数器目的:作为当前线程所执行字节码的行号指示...
文章目录
- 运行时的数据区域
- 一.程序计数器
- 二.Java虚拟机栈
- 局部变量表:
- 操作数栈
- 三.本地方法栈
- 四.Java堆
- 五.方法区(非堆)
- 运行时常量池
- 直接内存
运行时的数据区域
一.程序计数器
目的:作为当前线程所执行字节码的行号指示器
原理:通过字节码解释器改变计数器的值来选取下一条字节码指令
特点:
1.占用较小的内存空间
? 2.每条线程需要一个独立的程序计数器
? 3.Native方法不需要程序计数器,因为它不需要解释器
? 4.不同线程的该内存区域相互独立
方法类型 | 计数器状态 |
---|---|
Java方法 | 记录正在执行字节码地址 |
Native方法 | 空 |
异常处理: 当没有内存区域可扩展的时候,抛出OutOfMemoryError
二.Java虚拟机栈
目的:描述Java执行时的内存模型
原理:当一个JAVA方法执行的时候,会在虚拟机栈上建立一个栈帧,用来保存 局部变量表,操作数栈,动态键栈,方法出入的信息(eg:方法返回值)。
特点:
1.广义上的栈就是指的是,虚拟机栈中的几部变量表
? 2.进入一个方法时,局部变量空间是确定的,不会再改变
? 3.不同线程的该内存区域相互独立
异常处理:
1.若线程请求的栈深度 > 虚拟机允许的深度,抛出StackOverflowError
? 2.若动态虚拟机栈可以动态扩展(绝大多数),若扩展时无法申请足够的内存,抛出 OutOfMemoryError
局部变量表:
目的:使用 局部变量表 完成参数值到 参数变量列表 的传递过程
原理:是一个以字长为单位的数组,用于存放方法参数 和 方法内定义的局部变量索引
索引类型包括:基本变量类型,对象引用类型, returnAdress类型
1.reference类型(对象引用类型),作为对象引用指针,指明了对象在 JAVA堆 中的起始地址 和在 方法区 的对象类型数据
2. returnAdress类型,指向一条字节码指令的地址
-
局部变量表中一个slot代表一个变量槽,长度和CPU架构的位长是相同的。
-
64位长度的long和double类型占用2个局部变量表空间(slot),其他的均为1个单位大小。
-
在第0位slot处存放该方法所属对象实例的引用(在Java堆中),程序中用
this关键字
进行访问 -
可复用:超出作用域的slot变量将被GC回收进行覆写
操作数栈
目的:作为JVM的工作区,对数据进行操作。
原理:同样也是一个以字长为单位的数组,用于存放操作数的值。大多数指令都要从这里弹出数据,执行运算,然后把结果压回操作数栈。
解析:
void Method(){
int a = 1;
int b = 2;
int result = a + b;
}
内部过程
1.在局部变量表分配三个slot,分别指向 a , b,result。其中 a,b有初值
2.将局部变量表中的a,b的值放入操作数栈。
3.在操作数栈中弹出a,b的值弹出进行运算,接着将结果压入操作数栈中。
4.从操作数栈弹出结果,放到局部变量表中result相应的位置
三.本地方法栈
目的:描述Native方法执行时的内存模型
原理: 形如Java虚拟机栈
特点: 不同线程的该内存区域相互独立
异常处理: 与Java虚拟机栈出现的异常是相同的
有些虚拟机会将本地方法栈与Java虚拟机栈合二为一(eg:HotSpot虚拟机)
四.Java堆
目的: 存放几乎所有对象的实例
原理: 将实例存放在一块 物理不连续,但是逻辑上连续的内存空间上。
特点:
1.是JVM管理的内存中最大的一块区域
? 2.所有线程共享一块内存区域
异常处理: 通常实例分配的时候,堆是可扩展的,但是当无法再扩展的时候,会抛出OutOfMemoryError
五.方法区(非堆)
目的: 作为Java堆的逻辑部分
原理: 存储已被虚拟机加载的 类信息,常量,静态变量,即时编译器编译后的代码 等数据
特点:
1.物理不连续
? 2.所有线程共享一块内存区域
? 3.可以选择不实现GC
异常处理: 虽然方法区是可以扩展的,但是当无法满足内存分配时,抛出OutOfMemoryError
运行时常量池
目的: 是方法区的一部分,用于存放编译期间生成的各种字面量与符号
原理: 在类加载后,将“常量”存放在该区域
特点: 动态性:在运行期间也能将新的常量放入池中
? eg:String类的intern方法(TODO )
JDK1.8后字符串常量池放到了堆中,不再是在方法区中,而是在Java堆中
直接内存
目的: 直接引用分配在Java堆外Native函数库的内存,避免了Java堆与Native堆来回复制操作
原理: 通过一个存储在Java堆中的DirectByteBuffer
对象,作为这块内存的引用进行操作
特点: 显然直接内存分配不受Java堆大小限制,但受到本机物理的内存大小限制。
异常处理: 当占用总和超出物理内存大小限制的时候,抛出OutOfMemoryError
本文标题为:深入理解Java虚拟机(二) --- JVM内存管理
基础教程推荐
- java实现多人聊天系统 2023-05-19
- Java实现线程插队的示例代码 2022-09-03
- springboot自定义starter方法及注解实例 2023-03-31
- Java数据结构之对象比较详解 2023-03-07
- JDK数组阻塞队列源码深入分析总结 2023-04-18
- Java文件管理操作的知识点整理 2023-05-19
- ConditionalOnProperty配置swagger不生效问题及解决 2023-01-02
- Java实现查找文件和替换文件内容 2023-04-06
- Java并发编程进阶之线程控制篇 2023-03-07
- java基础知识之FileInputStream流的使用 2023-08-11