深入理解java虚拟机
2022-06-06 13:22:07 0 举报
AI智能生成
深入理解java虚拟机(第三版)
作者其他创作
大纲/内容
三、程序编译与代码优化
10.前端编译与优化
javac编译期
准备
解析,填充符号表
词法,语法分析
填充符号表
插入式注解处理器的注解处理过程
分析与字节码生成
java语法糖
泛型
擦除式泛型
兼容早期无泛型版本
类型擦除
值类型与未来的泛型
自动装箱,拆箱 循环遍历
条件编译
常量if
11.后端编译与优化
即时编译器
解释器预编译器
解释节约内存
编译提升效率
分层编译
变异对象与触发条件
热点代码
被多次调用的方法
被多次执行的循环体
栈上替换
热点探测
基于采样的热点探测
基于计数器的热点探测
hotspot使用
方法调用计数器
回边计数器
热度衰减
提前编译
提前编译的优劣
即使编译占用程序运行时间
占用运算资源
给即时编译做缓存
即时编译器优势
性能分析制导优化
激进预测性优化
链接时优化
编译器优化技术
方法内联
目标方法复制到调用方法
CHA类型继承关系分析
非虚方法直接内联
虚方法 守护内联
逃逸分析
栈上分配
支持方法逃逸
不支持线程逃逸
标量替换
聚合量替换成不可分解的标量
不去创建对象
同步消除
一个对象不会逃逸到方法或线程之外
公共子表达式消除
表达式E计算过,变量值没变化
数组边界检查擦除
运行期检查提前到编译器
Graal
四、高效并发
12.java内存模型与线程
硬件的效率与一致性
CPU高速缓存
缓存一致性问题
MESI
java内存模型
主内存和工作内存
所有变量存在主内存
线程工作内存存副本
内存间交互
lock锁定
unlock解锁
read读取
load载入
use使用
assign赋值
store存储
write写入
子主题
volatile
保证可见性
禁止指令重排序
不能保证原子性
long和double
非原子性协定
存2个变量槽
读半个值概率很低
double不会读半个,浮点运算器保证
原子性,可见性,有序性
read、load、assign、use、store、write保证原子性
volitile保证可见性
新值立即同步到主存
每次使用从主内存刷新
sychronized,final保证可见性
volitile和sychronized保证有序性
先行发生原则
程序次序规则
线程内,流程控制,代码在前先执行
管程锁定规则
unlock先发生lock
volatile变量规则
写先于读
线程启动规则
Thread的start先于其他所有方法
线程终止规则
线程所有方法先于终止检测
线程中断规则
interrupt()方法先于被中断线程代码检测到中断的发生
对象终结规则
对象初始化先于finalize()
传递性
A先于B,B先于C,则A先于C
java与线程
实现线程3种方式
内核线程实现
1:1
用户线程实现
1:N
混合实现
M:N
java线程直接映射到操作系统原生线程实现
线程调度
协同式
抢占式
java使用
状态转换
新建
运行
无期限等待
期限等待
阻塞
java与协程
有栈协程
无栈协程
纤程
有栈协程
执行过程和调度器
调度器:Fork/Join池
13.线程安全与锁优化
线程安全
java语言中的线程安全
不可变
绝对线程安全
相对线程安全
线程兼容
线程对立
线程安全实现方式
互斥同步
临界区 CriticalSection
互斥量 Mutex
信号量 Semaphore
ReetrantLock
等待可中断
公平锁
可绑定多个条件
非阻塞同步
CAS
锁优化
自旋锁与自适应自旋
自旋默认10次
6自适应自旋
根据同一个锁自旋时间和拥有者状态决定
锁消除
锁粗化
轻量级锁
不是替代重量级锁
没有多线程竞争前提下,减少重量级锁互斥量的性能消耗
进入同步块,无锁
栈帧Lock Record
CAS尝试更新Mark Word指向 Lock Record
成功加锁
s失败
当前线程指向Lock Record,进入线程
2个线程竞争,变为重量级锁
Mark Work 存储指向调用栈中记录的指针
偏向锁
目的:消除无竞争下的同步原语
锁会偏向第一个获得它的线程
有竞争力,偏向消失
Mark Work存储偏向线程Id
计算hash无法进入偏向
一、自动内存管理
2.java内存区域与内存溢出异常
数据运行时数据区
程序计数器
java虚拟机栈
局部变量表
编译 基本数据 引用指针
方法出口
操作数栈
动态链接
本地方法栈
与 java虚拟机栈类似 为native服务
Hotspot中与java虚拟机栈合二为一
堆
可以划分线程私有缓冲区 TLAB
存储实例对象
方法区
存储
类的信息
常量
静态变量
即时编译器后的代码缓存
运行时常量池
编译期生成的字面量与符号引用
直接引用
直接内存
可以通过NIO,调用Native方法分配内存
存储在内存中的DirectByteBuffer对这块内存进行操作
不归jvm管理,受到机器内存限制
对象
创建
常量池定位符号引用,检测代表的类是否被加载解析
没有,类加载
分配内存
指针碰撞
标记压缩
特点规整
serial,ParNew
空闲列表
标记清除
cms这种
线程预分配缓存
TLAB
Thread Local Allocation Buffer
对对象进行必要设置
对象头
锁相关信息
执行构造函数
对象初始化
内存布局
对象头
运行时数据
hashCode,对象分代年龄
指向锁记录的指针
指向重量级锁的指针
偏向线程Id,偏向时间戳,对象分代年龄
类型指针
指向它的类型元数据的指针
数组
记录长度
实例数据
代码里定义的各种类型字段的内容
对齐填充
必须是8byte的整数倍
访问定位
栈 reference 堆
主流方式
句柄
对象移动,只移动句柄
指针
快
outOfMemeryError异常
堆
栈溢出
stackOverflowError
-Xss
栈深度
方法区运行时常量池溢出
jdk1.7
动态代理
jsp
osgi
直接内存溢出
dump没有明显异常
3.垃圾收集器与内存分配策略
哪些需要回收-对象已死
引用计数法
可达性分析
本地变量表引用的对象
静态属性引用的对象
常量引用的对象
JNI引用的对象
虚拟机内部 异常 类加载器
锁持有对象
JMXBean,JVMTI回调,本地代码缓存
引用类型
强
软
有用非必须
溢出前二次回收
弱
非必须
下次垃圾回收
虚
子主题
生存死亡
F-Queue队列
finalize()方法
回收方法区
废弃常量,
不使用类型
所有类型被回收
类加载器被回收
java.lang.Class没被引用
什么时候回收-垃圾回收算法
分代收集理论
Remembered Set
记录跨代引用
标记-清除
速度快
碎片化
标记-复制
实现简单
速度快
浪费空间
分配担保
存活超survivor,进入老年代
存活不高
关注效率
CMS
标记整理
移动式
没有碎片
关注吞吐量
Parallel
如何回收-hotspot算法实现
根节点枚举
OOPMap
特定位置-安全点
抢占式
不使用
主动式
内存保护陷阱
设置标志位
安全区域
不执行代码
记忆集和卡表
Card Table实现记忆集
卡页
写屏障
维护卡表
为共享
未脏 更新
并发的可达性分析
三色标记
出入 黑-》白
解决:增量更新
CMS
删除灰=》白
解决:原始快照
G1,Shenandoah
垃圾回收器
Serial
标记整理
单线程
客户端
ParNew
Serial并行版本
新生代-复制
老年代-标记整理
配合CMS使用
UseConMarkSweepGC
Parallel Scavenge
新生代
复制
吞吐量优先
UseMaxPauseMills
GCTimeRatio
Serial Old
标记整理
Paralle Old
多线程并发
标记整理
CMS
老年代
标记清除
步骤
初始标记
stw
并发标记
重新标记
stw
并发清除
重置线程
浮动垃圾 Concurrent Mode Failure
Full GC
jdk1.5 68
jdk1.6 92
Garbage First
jdk9 默认
Collection Set: CSet
Region
1-32M
大对象:超过Region一半
2个TAMS
MaxGcPauseMills
回收比分配慢-》fullgc
步骤
初始标记
修改TAMS
耗时短
并发标记
并发执行
重新处理SATB
最终标记
短暂暂停
少量SATB记录
筛选回收
Region价值成本排序
STW
存活复制新Region
特点
基于Region
占用10%-20%额外内存
复制+整理
Shenandoah
跨代共享:连接矩阵
步骤
初始标记
stw
并发标记
最终标记
SATB扫描
组CSet
小stw
并发清理
没有存活对象Region
并发回收
时间取决于回收集大小
读屏障和brooks Pointers
转发指针
cas
初始引用更新
就对象引用修正
很短停顿
并发引用更新
时间取决 引用数量
最终引用更新
修正GCRoot引用
stw
并发清理
ZGC
Region
2M小型
32M中型
不固定大型
并发整理
染色指针
虚拟内存映射技术
步骤
并发标记
stw
并发预备分配
Relocation Set 重分配集
决定复制对象
并发重分配
移动存活对象到Region
为Relocation Set 维护转发表
并发重映射
修正分配集中对象引用
垃圾收集日志
-XX:PrintGCDetails
-Xlog:gc
内存分配与回收策略
对象优先在Eden分配
不足Minor GC
大对象直接进入老年代
-XX:PretenureSizeThreshold
长期存活的对象进入老年代
15
-XX:MaxTenuringThreshold
对象年龄动态判定
Survivor年代相同综合大于Suvivor一半
年代大于等于直接进入老年代
空间分配担保
-XX:HandlePromotionFailur
是否允许担保失败
老年代最大连续空间大于晋升平均值
4.虚拟机性能监控,故障处理工具
基础工具
商业授权
JMC
正式支持
实验性
jps
jstat
jinfo
jmap
jhat
jstack
可视化工具
JHSDB
JCconsole
VisualVm
Java Mission Control
子主题
HotSpot虚拟机插件和工具
HSDIS:Jit生成代码反汇编
5.调优案例与分析实战
二、虚拟机执行子系统
6.类文件结构
Class类文件结构
无符号数
表
魔数与Class文件的版本
常量池
访问标志
类索引、父类索引、接口索引集合
字段表集合
类变量
实例变量
不包含局部变量
方法表集合
属性表集合
字节码指令
加载和存储
load
store
运算指令
add
su
div
rem
类型转换指令
7.虚拟机类加载机制
类加载时机
生命周期
加载
验证
准备
解析
初始化
使用
卸载
类加载过程
加载
全限定名-》字节流
类的Class对象=》方法区
验证
文件格式验证
魔数
版本
常量池
附加信息
元数据验证
父类
不允许继承的类
抽象
字段,方法和父类
字节码验证
语义合法
符号引用验证
全限定名找到类
方法,字段
修饰符
准备
静态变量分配初始值
解析
符号引用替换为直接引用
符号引用
字面量
描述引用的目标
直接引用
指向目标的指针、相对偏移量
句柄
类或接口的解析
字段的解析
方法的解析
接口方法的解析
初始化
clinit
clinit阻塞
类加载器
双亲委派模型
启动类加载器
\lib下
扩展类加载器
\lib\ext下
应用程序类加载器
破坏双亲委派
jdk1.2
1.2以后出现双亲委派
基础类型回调用户代码
JNDI、JDBC、JCE、JAXB、JBI
SPI
6ServiceLoader
责任链
线程上下文类加载器
Thread下setContext=ClassLoader
热部署
OSGI
以java.*开头的类,委派给父类加载器加载
否则,将委派列表名单内的类,委派给父类加载器加载
否则,将Import列表中的类,委派给Export这个类的Bundle的类加载器加载
否则,查找当前Bundel的ClassPath,使用自己的类加载器加载
否则,查找类是否在自己的FragmentBundel中,如果在,则委派给F让哥们太 Bundle的类加载器加载
否则,查找Dynamic Import 列表的Bundle,委派给对应的Bundle的类加载器加载
否则,查找失败
java模块化系统
Jdk9
模块化的类加载器
启动类加载器
平台类加载器
应用类加载器
用户自定义类加载
8.虚拟机字节码执行引擎
运行时栈帧
局部变量表
存方法参数
局部变量
变量槽
操作数栈
动态链接
运行期转化为直接引用
方法返回
退出
异常
方法调用
解析
类加载阶段将部分符号引用转为直接引用
分派
静态分派
依赖静态类型决定方法执行版本
重载
动态分派
重写
运行期确定版本
单分派和多分派
java是静态多分派
动态单分派
虚方法表提升性能
方法入口地址
类型继承关系分析、守护内联、内敛缓存
动态类型语言
类型检查发生在运行期
java.lang.invoke
方法句柄=》MethodHandle
invokedynamic
动态调用点
基于栈的字节码解释执行引擎
解释执行
基于栈的指令集与基于寄存器的指令集
基于栈的解释执行过程
9.类加载及执行子系统的案例与实战
Tomcat:正统的类加载器架构
部署在同一台服务器上的两个web应用程序类库隔离
部署在同一台服务器上的两个web应用程序类库共享
服务器保证自身安全不受web程序影响
支持jsp,支持Hotspot
OSGI
字节码生成与动态代理
0 条评论
下一页