JVM基础原理
jvm基础
jvm是什么?
jvm是运行在操作系统上的执行.class文件的虚拟机
jvm与操作系统的关系?
相同点都是可以执行对应的程序
不同点是jvm是可执行class文件与操作系统中间的一层(ps:某人说过计算机世界中的问题如果一个中间层不能解决就再加一个☺️)
jvm、jdk、jre之间的关系?
- jdk>jre>jvm>操作系统
java虚拟机规范与Java语言规范之间的关系?
java虚拟机规范是定义执行.class文件的虚拟机的规范;
java语言规范是定义java文件的规范
jvm中的内存划分
java比c等系列的语言引以为豪的就是引入来自动内存管理机制,不让使用者在关心内存的管理。
- 内存划分
- 堆区
- 栈区(本地方法栈、java虚拟机栈)
- 程序计数器
- 本地内存(元空间、直接内存)
堆区
堆是一个由线程之间共享的内存区域。基本类型的对象会中栈上进行分配,而普通类型的对象会栈堆上进行分配。由于栈是线程独立的,因此就不存在并发问题
栈区
- 虚拟机栈
Java虚拟机栈是基于线程级别的,每个线程都拥有独立都虚拟机栈。虚拟机栈的作用是存储栈帧,栈帧的作用是是保存每个线程当前运行方法的状态或值。
栈值中分为:
- 局部变量表(用于存放方法参数和方法内定义的局部变量)
- 操作数栈(存放方法运行期间的操作数或结果)
- 动态连接(方法调用过程中的动态连接)
- 方法返回地址
程序计数器
程序计数器是用来标记当前线程正在执行的程序运行到哪了一行。
元数据空间
元数据空间是JDK8中划分出来的,用于替代JDK7已经之前的Perm区(永久代)。
元数据空间存储class信息、常量池、方法数据、方法代码等等
小结
jvm中运行的参数是在栈上的信息,栈上保存的引用指向的是堆中的对象,类信息、常量等信息则是放在元数据空间中。
对象创建的过程
- 类加载检查
- 分配内存空间
- 设置对象的头部信息(对象的类型、hashcode、锁状态等)
- 执行init方法(初始化)
- 返回对象的引用
对象的有两种创建方式,一种是通过TLAB分配内存,另一种是通过CAS + 自旋锁分配内存。
TLAB (Thread Local Allocation Buffer) 的使用场景:
- 适用场景:
- 小对象优先: TLAB 主要用于分配小对象。 这里的“小”是相对于整个堆空间而言的,具体大小由 JVM 的配置参数决定(例如,
TLABSize
)。通常,这个值设置为几 KB 到几十 KB。 - 线程频繁创建对象: TLAB 的优势在于避免了线程间的竞争,因此特别适合线程频繁创建对象的场景。例如,Web 服务器处理大量请求时,每个请求处理线程可能会创建很多临时对象。
- 内存分配速度敏感的应用: 由于 TLAB 分配不需要同步,速度非常快,因此对内存分配速度要求高的应用场景非常适用。
- 小对象优先: TLAB 主要用于分配小对象。 这里的“小”是相对于整个堆空间而言的,具体大小由 JVM 的配置参数决定(例如,
CAS + 自旋锁 的使用场景:
- 适用场景:
- 大对象: 当对象的大小超过 TLAB 的限制时,必须直接在共享堆中分配内存。
- TLAB 分配失败: 当 TLAB 空间不足时,线程需要从共享堆中重新申请新的 TLAB 或直接分配对象。
- 高并发环境: 虽然 TLAB 减少了线程间的竞争,但在并发量非常高的场景下,仍然可能出现多个线程同时尝试在堆中分配内存的情况。
- 竞争不是特别激烈的场景: 自旋锁适用于竞争不是特别激烈的场景。如果竞争非常激烈,线程长时间自旋会消耗大量的 CPU 资源。
小结:
- 优先使用 TLAB: JVM 会尽可能地使用 TLAB 来分配小对象,以提高分配速度和减少线程间的竞争。
- TLAB 不足时使用 CAS + 自旋锁: 当 TLAB 空间不足或需要分配大对象时,JVM 会使用 CAS + 自旋锁 来在共享堆中分配内存。
- 动态调整和优化: JVM 会根据具体的应用场景和硬件环境,动态调整 TLAB 的大小和自旋锁的策略,以达到最佳的性能和资源利用率。
更形象的比喻:
- TLAB 就像每个线程的“私人储物柜”: 线程可以快速地将一些常用的物品(小对象)存放在自己的储物柜中,无需和其他线程竞争。
- CAS + 自旋锁 就像“公共储物柜”: 如果物品太大或私人储物柜已满,线程需要到公共储物柜中寻找空间。如果公共储物柜正在被其他线程使用,则需要等待(自旋)直到可用。
类的加载机制
流程
加载 > 验证 > 准备 > 解析 > 初始化
类加载器
- Bootstrap ClassLoader
最底层的类加载器,用于加载java底层类的类加载器
- Extention ClassLoader
扩展类的类加载器,用于加载lib/ext下的文件
- App ClassLoader
应用加载器,用于加载classPath下的文件
- Custom ClassLoader
自定义的类加载器