类加载
类加载子系统的作用
ClassLoader的角色
类加载过程: 加载->链接->初始化
加载
链接
初始化
其中number会在链接阶段的准备阶段会初始化为0 ,然后到初始化阶段执行clinit时先将变量赋值20然后再赋值为10
注意:如果没有类变量,则字节码文件中不会存在clinit方法
eg:
类加载器分类
String加载器是使用引导类加载器加载
注: java核心类库都是使用引导类加载器加载的
引导类加载器
扩展类加载器
应用程序加载器
获取加载类的路径
需要自定义加载类的情况
隔离加载类:在某些框架需要使用中间件,但是中间件有自己的框架,在一个项目中同时引入多个框架可能导致冲突,主要是指路径相同,名称相同的类避免冲突
修改类加载的方式: 动态加载用到
扩展加载源: 有可能从数据库中加载类
防止源码泄露: java代码容易被反编译
自定义加载类实现步骤:
重写findClass()方法
如果没有复杂需求可以直接继承URLClassLoader
双亲委派机制
如果定义了一个跟和核心类一样的包和路径,就不会执行,还是执行核心类
eg:
当app加载类接收到加载请求时,它会向上委托,如果还有父加载器,则继续向上委托
如果父类中能找到对应的类,就完成加载,如果没有找到,则最后让子类加载
eg:
因为这个类要执行main方法,就要一层层往上找
当找到核心类String就加载了,结果核心类中的String没有main方法,所以报错
优点
沙箱保护机制
两个对象相等
类的主动使用和被动使用
运行时数据区
内存布局
具体划分
一个jvm实例对应一个runtime对象
线程
程序计数器(PC寄存器)
作用:存储指向下一条指令的地址,由执行引擎读取下一条指令
线程私有的,每个线程都有一个
final关键字
++x涉及到改变x的值,所以会报错,而x+1不会修改x的值,所以不会报错
o声明为final不能再变,但是对象里面的属性可以变
使用pc寄存器存储字节码指令地址有什么用
为什么使用pc寄存器记录当前线程的执行地址
cpu时间片
虚拟机栈
虚拟机栈概述
栈是运行时的单位,而堆是存储时的单位
栈解决程序运行问题,程序如何执行,或者如何处理数据,堆解决的是数据的存储问题,即数据如何放,放哪里
栈中可能出现的异常
设置栈大小
-Xss 设置最大栈空间
栈的存储单位
每个线程都有自己的栈, 栈中的数据都是以栈帧的格式存在
栈帧内部
局部变量表
局部变量表中的变量是重要的根节点,只要被局部变量表中直接或者间接引用的对象都不会被回收
操作数栈
动态链接
方法的调用
非虚方法
方法调用: 虚方法与非虚方法
动态语言和静态语言
方法返回地址
本地方法栈
堆
堆核心概述
设置堆内存大小与OOM
MinorGC MajorGC FullGC
MinorGC发生时间
老年代GC
内存分配策略
TLAB
堆空间参数设置
如果edgen区设置的过大,容易导致s0和s1区装不下回收后还剩下的对象
容易导致对象没有达到阈值就进入老年区了
如果edgen区设置的过小,容易导致垃圾回收的次数过多
空间分配担保
堆是分配对象存储的唯一选择吗
逃逸分析可以使对象分配到栈上,减少堆上垃圾回收的时间
代码优化之同步省略
代码优化之标量替换
方法区
运行时数据区结构图
从线程共享与否的角度看
栈,堆,方法区的交互关系
方法区的理解
设置方法区大小与OOM
如何解决OOM
方法区内部结构
类型信息
域信息
方法的信息
运行时常量池
常量池,可以看做是一张表,虚拟机指令根据这张常量表找到要执行的类名,方法名,参数类型,字面量等类型
方法区演进细节
方法区的垃圾回收
对象实例化
对象创建步骤
直接内存
好处
缺点
执行引擎
执行引擎概述
执行引擎工作过程
java代码编译和执行过程
JIT编译器
String的不可变性
intern使用
垃圾回收
标记阶段
对象存活判断
引用计数算法
java没有使用这种算法
如果使用这种算法,则下图就会出现垃圾没有回收的现象
可达性分析算法
分析prof文件
清除阶段
标记-清除算法
缺点:
复制算法
标记-压缩算法
对比
分代收集算法
分区算法:将所有的内存分成一个一个块
垃圾回收相关概念
System.gc()
内存溢出OOM
内存泄漏
stop the world
安全点与安全区域
安全区域
引用
软引用:内存不够即回收,常用于高速缓存
弱引用:发现即回收
虚引用
终结器引用
垃圾回收器
垃圾回收分类
按照工作模式区分:
评估GC性能指标
7款经典的垃圾回收器
组合关系
jinfo查看信息
Serial回收期:串行回收
优点
现在只有单核的cpu才会用串行的收集器,一般都不再使用
ParNew回收期:并行回收
ParNew除了并行之外,跟串行的收集器没有啥区别
新生代用并行方式,老年代用串行方式
Parallel Scavenge回收期:吞吐量优先
java8默认的垃圾收集器
参数设置
CMS回收期:低延迟
CMS工作原理
总结
G1回收器:区域化分代式
为什么叫G1
优点:
适用场景
分区Region:化整为零
大对象区:
G1回收器垃圾回收过程
G1垃圾回收垃圾过程
年轻代
G1优化建议
垃圾回收器总结
垃圾回收器的选择
GC日志分析
ZGC的了解
Class文件结构
类文件结构有哪几个部分
1.魔数
2.Class文件版本号
3.常量池
4.访问标识
5.类索引,父类索引,接口索引
6.字段表集合
7.方法表集合
8.属性表集合
1.魔数 : CAFEBABY
2.Class文件版本号:
3.常量池
常量池表项中,用于存放编译时期生成的各种字面量和符号引用,这部分内容在类加载后进入方法区的运行时常量池存放
常量池计数器
4.访问标识
5.类索引,父类索引,接口索引
6.字段表集合
7.方法表集合
8.属性表集合
javap
字节码指令概述
加载指令
操作数栈
局部变量表
常量入栈指令
类的生命周期
基本数据类型由虚拟机定义
引用类型需要进行类的加载
验证
主动使用和被动使用
类的卸载
类加载器
不同加载器加载的对象不是同一个对象
引导类加载器
拓展类加载器
应用类加载器
自定义类加载器
获取类加载器
热替换
沙箱安全机制
性能调优
1.发现问题: 性能监控
GC频繁
cpu load过高
OOM
内存泄漏
死锁
程序响应时间过长
2.排查问题: 性能分析
打印GC日志,通过GCviewer分析日志信息
灵活运用命令行,jstack,jmap,jinfo
dump导出堆文件,使用内存分析工具分析文件
使用阿里Arthas或jsonsole实时查看jvm状态
jstack查看堆栈信息
3.解决问题: 性能调优
适当增加内存,根据业务背景选择垃圾回收器
优化代码控制内存使用
增加机器,分散节点压力
合理设置线程池线程数量
使用中间件提高程序效率,比如增加缓存,消息队列等