深入理解java虚拟机
2021-01-18 13:26:20 38 举报
AI智能生成
简单图
作者其他创作
大纲/内容
虚拟机性能监控故障处理工具
调优案例分析与实战
类文件结构
虚拟机字节码执行引擎
类加载与执行子系统实战
前端编译与优化
后端编译与优化
Java内存模型与线程
线程安全与锁优化
走进java
概述
java不仅仅是一门语言,它还是一个由一系列软件与规范组成的技术体系,提供了完整的用于软件开发和跨平台部署的支持环境,并广泛应用于嵌入式,移动终端,企业服务器,大型机等场合
优点
摆脱硬件平台的束缚,一次编译处处运行
提供了相对安全的内存管理和访问机制,避免了大部分内存泄漏和指针越界问题
实现了热点代码检测和运行时编译以及优化,使得java性能随着运行时间增长而增加
有一套完善的应用程序接口,有商业机构和开源社区的第三方类库
历史
1995
LTS
JDK8,JDK11,JDK17
java技术体系
JDK
java语言
Java虚拟机
Java类库API
JRE
Java虚拟机
Java SE类库API
展望
无语言倾向 Graal VM
向Native迈进 AOT ahead time of Complilation
新一代即时编译器Graal 编译器
Java内存区域
运行时数据区域
程序计数器
如果执行java方法,里面存虚拟机执行字节码的行号指示器;如果执行native方法,则为空
堆
存放对象实例数据
TLAB Thread Local allocation buffer
从线程共享的java堆中划分出多个线程私有的分配缓冲区,以提升对象分配效率(线程安全)
方法区
类型信息
常量池
符号引用
符号引用翻译出来的直接引用
字符串
静态变量
JIT编译后的代码缓存
本地方法栈
类似虚拟机栈,为执行native方法服务
虚拟机栈
虚拟机栈描述的是java方法执行的线程内存模型
栈帧的结构
局部变量表
方法出口
操作数栈
动态连接
直接内存/不属于运行时数据区的一部分
NIO类
一种基于通道和缓冲区的IO方式
它能够提供性能的一个原因是直接使用native函数分配内存,然后通过java堆的DirectByteBuffer对象作为这个内存的引用进行操作,这样可以在一些场景中提高性能,因为避免了在java堆和Native堆中来回复制数据 TBD 五种IO方式 ,java BIO/NIO/AIO
HotSpot虚拟机对象探秘
对象创建
流程
根据new对应的参数检查常量池定位到一个类的符号引用,并检查类是否已经被加载解析初始化
若没有,则执行相应的类加载操作
为新生对象分配内存
分配可用空间(指针碰撞/Compact算法,空闲列表/Sweep算法)
线程安全
方案一 对分配内存的操作进行同步处理, CAS加失败重试来保证原子性
方案二 TLAB优先
然后对内存进行零值初始化,并进行对象头的设置(对象类型指针,GC年龄, hashcode, 偏向锁等)
然后调用对象构造函数 即class文件中的<init>方法 进行初始化
对象内存布局
Header
Mark Word(32bit/64bit)
HashCode
GC分代年龄
偏向锁
对象类型指针
数组长度
Instance data
Padding
因为要求对象地址必须是8字节的整数倍
对象访问
直接指针访问
访问速度快
句柄访问
垃圾回收时不改变ref,只改变句柄里的值
OOM实战
OOM处理思路:1.根据dump出来的heapdump文件,用内存映像分析工具分析,判断OOM的对象是否必要的,是内存泄漏还是内存溢出。
如果是内存泄漏,通过工具查看从泄漏的对象出发,沿着引用链找到Gcroots, 从而定位到对象创建的代码位置,进而确定内存泄漏的代码位置,做
如果是内存溢出,需要对比虚拟机堆参数以及硬件内存, 修改堆参数的空间,并且从代码上检查是否存在某些对象生命周期过长,持有时间过长,设计不合理等情况。
如果是内存泄漏,通过工具查看从泄漏的对象出发,沿着引用链找到Gcroots, 从而定位到对象创建的代码位置,进而确定内存泄漏的代码位置,做
如果是内存溢出,需要对比虚拟机堆参数以及硬件内存, 修改堆参数的空间,并且从代码上检查是否存在某些对象生命周期过长,持有时间过长,设计不合理等情况。
垃圾收集器和内存分配策略
对象判活算法
引用计数法
基于GC root的可达性分析法
GCroot有哪些
栈中本地变量表引用的对象,如方法参数,局部变量,临时变量
本地方法区中JNI引用的变量
方法区中常量引用的对象
静态变量
被同步锁持有的对象
JAVA虚拟机内部的引用,如基本数据类型对应的Class对象,系统类加载器
反应JVM内部情况的JMXean JVMTI中注册的回调,本地代码缓存等
回收方法区
主要是对常量的回收,类型卸载
类型卸载条件
所有实例已经被回收
类加载器被回收
Class对象没有在任何地方被引用
引用类型
强
只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象
软
对于软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围之中进行第二次回收
弱
被弱引用关联的对象只能生存到下一次垃圾收集发生之前
虚
在这个对象被收集器回收时收到一个系统通知
垃圾收集算法
标记清除
概述
经典方法,有标记过程和清除过程
缺点
缺点分配的效率随着分配数量的增加而增加
空间碎片
优点
基础算法,不需要移动对象
标记复制
概述
内存分成两部分,一部分用于分配,一部分用于回收后新对象分配
优点
效率高,无碎片
缺点
只有一半空间被利用
标记整理
概述
标记+整理
优点
无内存碎片
缺点
需要移动对象
问题
移动需要暂停所有用户线程的执行
不移动导致的空间碎片只能依赖复杂的内存分配和内存访问,而内存访问时用户程序最频繁的操作,弱国再这个环节增加了额外的负担,势必影响应用程序的吞吐量。
移动则回收复杂,不移动则分配复杂。所以根据收集器的目标来确定相应的算法
分代收集思想
弱分代假设
大多数对象朝生夕灭
强分代假设
熬过多次收集对象难以消亡
设计原则
java堆划分成不同的区域,然后根据gc年龄分配到不同区域中存储。并且适用不同的收集算法
跨代之间引用假设
跨代引用较少,同一年代的对象倾向于同时生存或者同时消亡
常见垃圾收集器
Serial
ParNew
Pascavenge
CMS
Serial Old
Parrelle Old
G1
垃圾收集器选择策略
原则
目标
响应时间
网页
吞吐量
计算任务
内存占用
嵌入式
硬件情况
体系结构
硬件
操作系统
JDK版本
过程
有钱 商用方案
否则 Z
如果是windows 考虑 S
否则如果JDK版本老,或者是遗留系统
堆大小小于6G
CMS
大于6G
G1
低响应速度垃圾收集器
S
Z
虚拟机类加载机制
类生命周期
加载
连接
校验
方法调用
直接引用转间接引用
简单初始化
初始化
使用
卸载
类加载器的双亲委派模型
系统类加载器
启动类加载器
扩展类加载器
应用程序类加载器
收藏
0 条评论
下一页