提升后端知识 第一天内容
运行时数据区域
因为把控制内存的权力交给的虚拟机 使用时并不关注 所以内存泄露和溢出时才束手无策
运行时数据区
虚拟机会把管理的内存划分数据区域
问题: 生命周期
区域划分
| 内存区域 | 我的初步理解 |
|---|---|
| 方法区 | 存放方法的区域? |
| 堆 | 放引用数据类型变量的地方? |
| 虚拟机栈 | 调用方法区和堆的平台可以拿来放这里? |
| 本地方法栈 | 调用方法区提出来放这里,好像和虚拟机栈冲突? |
| 程序计数器 | 标记方法和变量内存用了几次? |
运行时数据区分为线程共享和线程隔离
| 其它 | 我的初步理解 |
|---|---|
| 执行引擎 | 能驱动方法执行的 |
| 本地库接口 | 能通过这个调用本地方法方法库 |
| 本地方法库 | jvm自带的方法 io网络等一系列底层方法 |
程序计数器
Program Counter Register
较小内存空间
线程私有
生命周期和线程一致
字节码行号指示器 字节码解释器可以通过它来读取字节码 当读取本地方法是为空
不会内存溢出
虚拟机栈
Java Virtual Machine Stack
线程私有
生命周期和线程一致
创建栈帧 存储局部变量 操作数 动态连接 方法出口
方法被调用到执行完毕 对应栈帧在虚拟机栈入栈到出栈
日常说的[栈内存]里面栈指的就是虚拟机栈
局部变量表 存放基本数据类型 对象引用 字节码指令地址
局部变量表有变量槽 64位(long double)占两个变量槽 其它占一个变量槽
局部变量表在编译期间完成分配 运行时需要在栈帧中分配多大局部变量空间完全确定 不会改变大小 内存是由虚拟机决定
线程请求栈深度大于虚拟机允许深度 会抛StackOverflowError
Java虚拟机栈容量可以动态扩展 栈扩展时无法申领足够的内存OutOfMemoryError异常
本地方法栈
为虚拟机使用的本地(Native)方法服务
虚拟机只会提供内存空间 不会具体管理执行细节
Java堆
虚拟机所管理的内存中最大的一块
所有线程共享
生命周期跟随虚拟机
存放对象实例
垃圾收集器管理区域
划分
多个线程私有的分配缓冲区(Thread Local Allocation Buffer,TLAB)
方法区
线程共享的内存区域
用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据
JDK8废弃永久代 放入元空间
运行时常量池
是方法区的一部分
Class文件中有常量池表 用于存放编译器生成的各种字面量和符号引用
字面量
- 文本字符串:比如
"Hello World"。 - final常量值:比如
final int NUM = 10中的10。 - 基本类型的字面值:比如
3.14f(float)、true(boolean)。
符号引用
- 类和接口的全限定名:比如
java/lang/String。 - 字段的名称和描述符:比如你在代码里写的
user.name。 - 方法的名称和描述符:比如
sayHello()V(表示无参无返回值的sayHello方法)。
在Class时还没有分配内存 因此不存在内存地址
运行时常量池具备动态性 语言并不要求常量在编译期产生 运行时也可以将新的常量放入池中 例如:Stirng.intern
直接内存
并不是虚拟机运行时数据区的一部分 由于被频繁使用也可能会导致内存溢出
JDK 1.4加入了NIO 通过Native函数库分配堆内存
本机直接内存的分配不会受到Java堆大小的限制
会受到本机总内存(包括物理内存、SWAP分区或者分页文件)大小以及处理器寻址空间的限制
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!