JVM 深入理解Java虚拟机
2023-02-01 09:53:33 4 举报
JVM 内存结构图,包含类加载过程,对象创建过程,JIT编译器执行过程等,较为详细的展示JVM的知识点,文档还会持续更新。
作者其他创作
大纲/内容
大对象
链接
无锁
64bit
调用
否
1
Survivor(1/10)
Shenandoah
新生代(1/3)
设置对象头
解析与填充符号表
CAS +失败重试
findClass()
未分配
采样
关闭
编译
0001~1111
JIT
浮动垃圾
堆内存
修正并发标记变动的对象
没有加载
晋升老年代的条件:
有
是
请求编译
main
验证
延迟编译
from
....
尝试TLAB分配
栈上替换
偏向
筛选回收
文件格式校验
求和
15
替换方法地址
Serial(串)复制
空闲列表
操作数栈
对象头
0
。。。。
方法入口
线程id
Mark Word
对象创建过程
CMS(并发)清除
触发FullGC
GC
动态链接
控制分析
ExtClassLoader加载路径:jre/lib/ext/
解语法糖
大
方法区常量
只标记GCRoot直接关联的对象
本地方法的引用
font color=\"#e65100\
分层编译
轻锁
记忆集(数据结构)--卡表(具体实现)
不可达
class 指针
new
初始标记
FILO
TLAB
计数器 默认
Serial Old(串)整理
指针碰撞
大于当前空间总大小
clinit(){ a =10; b = 100; a = 20; }
本地方法
回边计数器
未
E
S
H
逃逸分析
栈上的变量
堆空间
数组长度
STW
方法区静态变量
指向栈中锁的记录指针
对象
运行时数据区
分配策略
Class Metadata Adderss
a = 10
初始化处理器
编译过
调用计数器+1
内联
方法数据
解释执行
初始化<clinit>()
方法出口
Array Lenth
直接引用
Epoch
Edn(8/10)
线程一
本地方法(栈)
加载
AppClassLoader加载路径:classPath/
局部表量表
非等待
线程安全
重复标记
空
标记复制
热度衰减
JIT:字节码->机器码(存入Code Cache)
自定义加载器反射
初始化
年轻代
并发清除
c2编译器
HashTable结构初始桶:60013最小:1009
BootstrapClassLoader加载路径:jre/lib/
Test.java
1. 年龄大于152. 大对象: . survivor 无法存储的对象 . 创建对象大于新生代空间
方法调用
空间不足
从直接关联对象遍历整个对象图
栈帧
Test.class
逃逸
阈值
00
Region
对齐填充
解释器
类装载子系统
方法代码
c1编译器
Hashcode(大小与虚拟机位数有关)
优化技术
Code Cache
11
程序计数器
创建
并发标记
注解处理
栈上分配
标量替换
锁消除
热点探测
老年代的GC条件:
find in cache()
10
符号引用
执行<init>
产生碎片空间
1001
GCRoot
锁膨胀
1b
老年代(2/3)
static int a =10; static int b =100; static{ a = 20; }
跨代引用
分析与字节码生成
数组
线程2
32bit
开启
语法、词法分析
分配内存
64个Regin card = 1个缓存行64×512字节=32kb内存 每个卡页的大小是512字节如果不同线程更新的对象正好处于这32KB的内存区域内
JVM 参数-Xms : 初始堆内存大小-Xmx : 最大堆内存大小-Xmn : 年轻代内存大小-XX:SurvivorRatio :Eden区与Survivor区的大小比值 -Xss : 每个线程的Stack大小-XX:G1HeapRegionSize
替换
TLAB(线程本地分配缓冲区)
分配方式
尝试年轻代上分配
触发SerialOld
伪共享:变量恰好共享同一个缓存行,彼此影响(写回、无效化或者同步)而导致性能降低,这就是伪共享问题。
标记清除
静态变量分配内存
在线程进行加锁时,如果该锁对象支持偏向锁,那么 Java 虚拟机会通过 CAS 操作,将当前线程的地址记录在锁对象的标记字段之中,并且将标记字段的最后三位设置为 101。在接下来的运行过程中,每当有线程请求这把锁,Java 虚拟机只需判断锁对象标记字段中:最后三位是否为 101,是否包含当前线程的地址,以及 epoch 值是否和锁对象的类的 epoch 值相同。如果都满足,那么当前线程持有该偏向锁,可以直接返回。
同步消除
提交OSR栈上编译请求
每512字节的连续区域会被定位到同一片卡表区域当老年代持有新生代的引用则regin对应的 bit=1
类型断言
静态表量
重锁
01
指向互斥量的指针
类元数据校验
委派
减少回边计数器值
ZGC
对象的hashcode
偏向锁标记
类元数据
可达对象
失败
HotSpot VM的锁实现机制是:当一个对象已经计算过identity hash code,它就无法进入偏向锁状态;当一个对象当前正处于偏向锁状态,并且需要计算其identity hash code的话,则它的偏向锁会被撤销,并且锁会膨胀为轻量级锁或者重量锁;轻量级锁的实现中,会通过线程栈帧的锁记录存储Displaced Mark Word;重量锁的实现中,ObjectMonitor类里有字段可以记录非加锁状态下的mark word,其中可以存储identity hash code的值。
Parallel(并)复制
Parallel Old(并)整理
常量池
填充符号表
锁标记(2bit)
b = 100
G1(并发)复制+整理
对象赋值、执行构造方法
解析
生成字节码
回边计数器+1
字符串常量池
执行 编译器 把静态变量、静态方法构建的clinit()方法只加载一次
类加载检查
执行引擎
尝试栈上分配
执行器
MESI协议
编译器
尝试老年代上分配
字节码校验
解释器:字节码->机器码(重复执行)
JVM内部引用
静态变量赋初值int a = 0;
this
字节码指令:ldc 从运行时常量池推送项目astore_<n> 存储reference到局部变量invokespecial 调用实例方法;对超 类、私有和实例初始化方法调 用的特殊处理dup 复制顶部操作数堆栈值iconst_ 推int常数aload reference从局部变量加载
标注检查
消除冗余
引用符号校验
分代年龄(4bit)
栈(线程)
线程参数、局部表量、临时变量
hashCode方法可以被重写并返回重写后的值identityHashCode不管是否重写都返回地址计算的hash值
1.类型擦除(泛型)2.插箱、装箱3.遍历4.变长参数...
线程独享
类变量分配内存
最终标记
准备
方法区
Class
老年代
实例数据(属性)
实现:写屏障维护卡表问题:1.开销; 2.伪共享;解决:不采用无条件的写屏障 1.先检查卡表标记 2.是否开启卡表更新-XX+UseCondCardMark
大于
成功
标记字
幸存者
大于年轻代空间
ParNew(并)复制
同步锁持有对象
常驻异常对象
减小保证编译完成前继续使用解释执行,降低循环判断次数
栈上分配内存
to
回边指令
0 条评论
下一页