Java 虚拟机
2023-06-09 13:57:15 3 举报
AI智能生成
Java 虚拟机
作者其他创作
大纲/内容
类文件结构
文件格式
魔数(Magic Number)
版本号(Version)
常量池(Constant Pool)
计数器(constant_pool_count)
字面量(Literal)
符号引用(Symbolic References)
类和接口的全限定名(Fully Qualified Name)
字段的名称和描述符(Descriptor)
方法的名称和描述符
表项与 TAG 值
访问标志(Access Flags)
类索引(This Class)、父类索引(Super Class)与接口索引集合(Interfaces)
字段表集合(Field Info)
全限定名
简单名称
描述符
方法表集合
属性表集合
Code
字节码指令
显式异常处理表
StackMapTable
Exceptions
LineNumberTable
SourceFile
ConstantValue
InnerClasses
Deprecated
Syntheic
Signature
BootstrapMethod
实例分析
字节码指令
数据类型
加载与存储指令
运算指令
类型转换指令
对象创建与访问指令
操作数栈管理指令
控制转移指令
方法调用和返回指令
异常处理指令
同步指令
类加载机制
类加载过程
加载(Loading)
非数组类
1. 获取二进制字节流
2. 生成运行时数据结构(方法区)
3. 生成 Class 对象(堆)
数组类
连接(Linking)
验证(Verification)
文件格式验证
语义检查
字节码验证
符号引用验证
准备(Preparation)
1. 内存分配
2. 创建数据结构
符号引用
非接口负号引用
接口符号引用
方法表
3. 设置默认值
解析(Resolution)
直接引用
方法指针
方法表索引
触发错误
解析类或接口
解析字段
解析方法
解析接口方法
初始化(Initialization)
触发条件
执行新建类实例的指令 new
执行调用静态方法的指令 invokestatic
执行访问静态字段的指令 getstatic/putstatic
使用 java.lang.reflect API 对某类进行反射调用
子类初始化触发父类初始化
JVM 启动时初始化用户指定的主类
定义了 default 方法的接口,接口被实现时
初次调用 MethodHandle 实例
......
被动引用(不触发)
通过子类引用父类静态字段,不会触发子类初始化
通过数组定义来引用类,不会触发类初始化
引用定义在类中的常量,不会触发类初始化
<clinit> 方法
区别于 <init>
接口与类
执行步骤
对类进行加载和连接
优先初始化父类
依次执行类初始化语句
类加载特征
双亲委派模型
类加载器
启动类加载器(Bootstrap ClassLoader)
扩展类加载器(Extention ClassLoader)
应用类加载器(Application ClassLoader)
自定义类加载器(Self-defined Classloader)
不遵循模型
Tomcat
SPI
JDBC MySQL 驱动加载
加载原理
OSGi
替换 JDK 类
提高类加载效率
AOT
AppCDS(Application Class-Data Sharing)
类的动态加载
从字节码到 Class 对象
生成字节码
字节码操作类库
自己实现动态代理
平台模块化系统(JPMS)
扩展类加载器被平台类加载器取代
平台类加载器和应用程序类加载器不再派生自 java.net.URLClassLoader
获取启动类加载器仍然返回 null
对于双亲委派模型,在向上委派时,优先委派给模块的类加载器
方法调用机制
参数传递
重载与重写
二义性
重载:针对同名不同参方法
选取规则
重写:针对继承同名同参方法
重写方法的返回类型不一致
泛型参数类型造成的方法参数类型不一致
方法调用指令
静态绑定:编译时绑定
非虚方法
静态方法调用:invokestatic
私有实例方法、构造方法、super 调用:invokespecial
动态绑定:运行时绑定
虚方法
非私有方法调用:invokevirtual
接口方法调用:invokeinterface
方法表:解析虚方法调用时
内联缓存:即时编译器
缓存类型
重新绑定
方法句柄(MethodHandle)
Lambda 表达式
异常处理
Throwable
Checked Exception
IOException
Unchecked Exception
Error
* LinkageError
* VirtualMachineError
RuntimeException
NullPointerEception
ClassCastException
SecurityException
捕获异常
异常表
异常表匹配
执行路径
finally 与 return 的问题
Supressed 异常
try-with-resources
多种异常捕获
设计原则
尽量不要通用地捕获异常
不要生吞(Swallow)异常
区分异常是否可恢复
异常输出中避免包含敏感信息
......
类型关系
基本类型与包装类型
数组与 List
数组访问
注解(Annotation)
动态代理(Dynamic Proxy)
反射(Reflection)
基本应用
委派实现、本地实现
动态实现
性能开销
反射 API
JDK Proxy
cglib
字节码执行引擎
运行时栈帧结构
局部变量表
基本类型变量
Slot 复用
操作数栈
动态连接
方法返回地址
附加信息
方法调用
解析
分派
静态分派
重载方法
动态分派
单分派与多分派
动态类型语言支持
方法句柄(MethodHandle)
与反射(Reflection)的区别
基于栈的字节码解释执行引擎
解释执行
基于栈的指令集与基于寄存器的指令集
基于栈的解释器执行过程
内存区域
JIT 代码缓存(Code Cache)
运行时数据区(Runtime Data Area)
线程私有区域
* 本地方法栈(Native Method Stack)
程序计数器(Program Counter Register)
Java 虚拟机栈(JVM Stack)- 栈帧(Stack Frame)
操作数栈(Operand Stack)
局部变量表(Local Variable Array)
基本数据类型
对象引用(reference)
字节码指令地址(returnAddress)
动态链接
方法出口
常量池引用(Reference to Constant Pool)
线程共享区域
堆(Heap)
新生代(Young Generation)
Eden
线程私有缓冲区(TLAB)
From Survivor
To Survivor
老年代(Old Generation)
* 永久代(Permanent Generation,JDK 1.8-)
字符串常量池
类文件常量池
直接内存(Direct Memory)
元空间(Meta Area)
方法区(Method Area)
运行时常量池(Runtime Constant Pool)
类的版本、字段、方法,接口,静态静态变量等描述信息
对象管理
数据类型
基本类型
默认值与值域
浮点型
自动装箱与自动拆箱
引用类型
类与接口
数组类
泛型参数
创建方式
无参构造器
父类构造器
创建过程
JVM:创建对象
1. 类加载检查
2. 分配内存
内存规整(Compact):指针碰撞(Bump the Pointer)
Serial
ParNew
......
内存不规整(Mark-Sweep):空闲列表(Free List)
CMS
......
栈上分配
逃逸分析
3. 内存初始化
4. 对象设置
所属类的实例
类元数据信息
对象哈希码
对象 GC 分代年龄
......
Java 程序:对象初始化
对象内存布局
对象组成
对象头(Header,16byte)
标记字段(Mark Word,64bit)
哈希码(25bit)
GC 分代年龄(4bit)
锁状态标志(2bit)
线程持有的锁
偏向线程 ID
偏向时间戳
......
类型指针(Klass,64bit)
* 数组长度记录
实例数据(Instance Data)
存储顺序
分配策略
父类、子类
对齐填充(Padding)
访问定位
句柄(池)
直接指针
内存压缩与对齐
压缩指针
内存对齐
字段重排列
虚共享
深堆与浅堆
内存溢出异常(OOM)
堆
虚拟机栈和本地方法栈
StackOverflowError
OutOfMemoryError
方法区和运行时常量池
方法区
运行时常量池
直接内存
GC 效率低下
String 内存泄漏
垃圾收集机制
分代收集理论
弱分代假说
强分代假说
跨代引用解说
对象判断
判断算法
* 引用计数(Reference Counting)
可达性分析(Reachability Analysis)
GC Roots
JVM 栈栈帧的局部变量表中引用的对象
本地方法栈中 JNI 中引用的对象
方法区中类静态属性引用的对象
方法区运行时常量池中常量引用的对象
JVM 内部的引用
所有被同步锁持有的对象
反映 JVM 内部情况的 JMXBean、JVMTI 中注册的回调、本地代码缓存等
......
引用定义
引用类型
强引用(Strongly Reference):永远有效
软引用(Soft Reference):内存不足
弱引用(Weak Reference):下次 YGC
虚引用(Phantom Reference):即时失效
自我拯救
finalize() 方法
垃圾定义
回收方法区
废弃常量
无用的类
垃圾收集算法
垃圾收集分类
部分收集(Partial GC)
新生代收集(Minor GC/Young GC)
老年代收集(Major GC/Old GC)
混合收集(Mixed GC)
整堆收集(Full GC)
* 引用计数式(Reference Counting GC):直接
追踪式(Tracing GC):间接
标记 - 清除(Mark-Sweep)
标记 - 复制(Mark-Copy)
标记 - 整理(Mark-Compact)
分代(Generational Collection)
新生代:标记-复制
老年代:标记 - 清除 或 标记 - 整理
HotSpot 实现
枚举根节点
OopMap
安全点(Safepoint)
Java 线程的状态
中断
* 抢先式(Preemptive Suspension)
主动式(Voluntary Suspension)
检测
解释执行字节码
执行 JIT 机器码
安全区域(Safe Region)
记忆集(Remembered Set)
字长精度
对象精度
卡精度
脏卡查找
引用更新
卡标识位与写屏障
写屏障(Write Barrier)
虚共享
并发可达性分析
三色标记法(Tri-color Marking)
对象消失问题
增量更新:CMS
原始快照:G1、Shenandoah
垃圾收集器
年轻代(标记-复制)
Serial(串行单线程)
ParNew(串行多线程)
Parallel Scavenge(吞吐量优先)
老年代(标记-整理 或 标记-清除)
Serial OId(MSC)
Parallel Old
CMS(并行)
1. 初始标记
2. 并发标记
3. 预清理
4. 重新标记
5. 并发清除
碎片整理
G1(Garbage First,并行)
设计特点
划分区域
权衡收益
缓存定位
空间整合
可预测停顿
避免干扰
执行流程
1. 初始标记
2. 并发标记
3. 最终标记
4. 筛选回收
执行流程(另一种角度描述)
1. 初始标记(新生代回收)
2. 并发标记(老年代回收)
3. 混合回收
Low-Pause-Time(低延迟)
ZGC
并发标记
并发预备重分配
并发重分配
并发重映射
Shenandoah
初始标记
并发标记
最终标记
并发清理
并发回收
初始引用更新
并发引用更新
最终引用更新
并发清理
Epsilon(不收集)
内存管理
线程安全
TLAB:划分不同空间执行内存分配
同步:对分配内存空间进行同步处理(CAS)
分配策略
对象优先在新生代 Eden 区分配
大对象直接进入老年代:-XX:PretenureSizeThreshold
长期存活的对象进入老年代:-XX:MaxTenuringThreshold
动态对象年龄判定:-XX:TargetSurvivorRatio
老年代空间分配担保
GC 触发条件
Minor GC
新生代 Eden 区内存不足
标记 - 复制
Full GC
调用 System.gc()
老年代内存不足
空间分配担保失败
Concurrent Mode Failure
Full GC 测试
永久代不足(<= JDK 1.7)
0 条评论
下一页