Linux IO 模型
1.阻塞IO
2.异步非阻塞IO
3.IO复用
4.信号驱动IO
5.异步IO
Java 类加载器
自定义类加载器 Custom ClassLoader
启动类加载器 Application ClassLoader
扩展类加载器 Extension ClassLoader
引导类加载器 Bootstrap ClassLoader
类加载机制
通过编译器把.java文件编译成.class文件
加载
链接
验证
class文件格式验证
准备
变量初始化
final变量赋值
解析
符号引用->直接引用
初始化
类的初始化
使用
卸载
类的加载器 ApplicationClassCloader:应用类程序加载器 ExtClassCloader:扩展类程序加载器 BoostrapClassCloader:启动类程序扩展类加载器 线程状态 Java 新建:new 运行:runnable 等待:watting 现实等待:time watting 阻塞:boloked 结束:terminated
JVM运行时数据区 线程私有: 程序计数器 记录程序运行位置 线程私有栈(虚拟机栈) 局部变量表 操作数栈 动态链接 方法返回地址
本地方法栈
通过JNI调用c,c#语言的方法
线程共享:
堆
方法区
具体实现
1.8之前:永久代,在堆内存中
1.8之后:元空间,在OS的内存中
空间布局
新生代 1/3
伊甸园 8/10
from区 1/10
to区 1/10
老年代 2/3
对象什么时候进入老年代
1.15次gc之后
对象对象头的分代是4bit,区间是0-15
2.大对象直接进入
大于Eden50%,运行时动态调整
3.空间担保
gc之后,剩下对象还是大于from区
4.动态
大于Eden和from区
jvm调优
-Xms:最小堆内存
-Xmm:最大堆内存
-Xmn:新生代大小
-MaxMetaspaceSize:元空间最大内存
-MinMetaspaceSize:元空间最小内存
-Xss:虚拟机栈的大小
执行引擎 解释器 字节码解释器:解释执行 Java字节码 -> c++ -> 硬编码
模板解释器:编译执行
Java字节码 -> 硬编码
即时编译器(编译给模板解释器使用的)
C1编译器:client模式下的即时编译器
1.触发条件比C2比较宽松:需要收集的数据比较少
2.编译优化的比较浅:基本运算子啊编译的时候去掉了
3.c1编译器编译生成的代码执行效率比C2低
C2编译器:server模式下的即时编译器
1.触发条件比较严格,一半来说,程序运行一段时间以后触发
2.优化比较深
3.编译生成的代码执行效率较C1更高
触发条件:
硬编码
热点代码
最小单位不是一个函数,而是代码块(for,while)
程序初期触发C1即时编译器
程序运行一段时间之后触发C2编译器
clien模式下
N的默认值:1500
server模式下
N的默认值:100000
硬编码
热点代码块
保存在方法区:CodeCash
server编译器模式下-代码缓存大小起始于160K
client编译器模式下-代码缓存大小起始于2496K
热度衰减
LRU算法
阿里热冷机切换事故(热机:指代码运行一段时间的机器;冷机:新机器)
因为但是代码触发及时编译优化,流量瞬间打过去,冷机器就直接挂了,优化之后的代码,执行效率更高,所以能抗住更多的并发
即时编译是怎么运行的
通过VM_THREAD线程(守护线程)例如:
GC
即时编译器
将这个及时编译任务写入队列queue
vm_thread从这个队列中读取任务,并运行
即时编译器有多少线程,如何调优
java -client -XX:+PrintFlagsFinal -version | grep CICompilerCount
-XX:CICompilerCount=N
查看具体JVM数据:java -client -XX:+PrintFlagsFinal -version | grep CompileThreshold(筛选CompileThreshold参数,不筛选默认打印全部参数)
即时编译优化技术
逃逸分析
什么叫逃逸:变量会被其他线程改动
共享参数
返回值
参数
逃到哪里去
方法外
线程外
什么情况不逃逸
对象和变量作用域是局部的
所以说局部的变量和对象不会逃逸的
基于逃逸分析现象,JVM开发了三种优化技术
逃逸分析默认是开启的
1.栈上分配
对象在堆种分配
TLAB:线程私有也会分配对象
2.标量替换
对象final修饰的变量直接替换,编译优化
3.锁消除
局部变量作为锁,就会锁消除,JIT
pulic void syc(){
synchronized(new Test()){
doSomeThing()....
}
}
优化之后
pulic void syc(){
doSomeThing()....
}
即时编译器分析new Test(),不会发生逃逸,也不会存在锁竞争,所以消除了锁
jvm三种解释器模式
纯字节码解释器: -Xint
纯模板解释器 —Xcomp
字节码解释器 + 模板解释器 -Xmixed
程序越大 -Xmixed > -Xcomp > -Xint
事务 MySQL: 事务的隔离级别 1.读未提交:脏读,不可重复读,幻读 2.读已提交:不可重复读,幻读 3.重复读:幻读 4.串行化:
不可重复读和幻读的区别:
一个事务读到修改的数据:不可重复读
一个事务读到新增和删除的数据:幻读
MySQL是怎么避免幻读的:MVCC(并发版本控制-快照读)
给每条行
Java类的加载机制
加载
把.java文件编译成.class文件
加载可以从多个地方加载,网络,本地文件,动态生成等
链接
验证:文件格式验证,元数据验证,
准备:变量初始化,final变量直接赋值
解析:间接引用改成直接引用
初始化
类的初始化
使用
卸载
类加载器
自定义类加载器
应用程序类加载器
扩展类加载器
引导类加载器
向上委托加载
运行时数据区 线程共享 方法区 局部变量表 方法返回地址 堆 1/64 新生代 1/3 Eden 6/8 from 1/8 to 1/8 老年代 2/3 线程私有 程序计数器 记录程序执行的位置 本地方法栈 Java native方法 虚拟机栈 局部变量表 操作数栈 动态链接 方法返回地址
执行引擎
jvm调优 -Xms:最小堆内存 -Xmm:最大堆内存 -Xmn:新生代大小 -MaxMetaspaceSize:元空间最大内存 -MinMetaspaceSize:元空间最小内存 -Xss:虚拟机栈的大小
mysql架构
网络接入层
服务层
储存引擎层
文件系统层
客户端 连接池 查询缓存:验证权限等 解析器:语法解析,解析树,预处理 优化器:查询优化器,SQL优化 执行引擎:调用储存引擎API 文件系统
索引 mysql 索引本身是为了高效检索数据设计的数据结构
索引类型
普通索引
唯一索引(主键索引)
全文索引
空间索引
常用存储引擎:
InnoDB:
表结构文件:.frm
数据文索引文件:.ibd
聚集索引:叶子节点储存行记录,二级索引叶子节点储存主键 key:主键 value:行记录
回表:通过二级索引查询到主键,在通过主键查询行记录 key:索引字段值 value:主键
索引覆盖:select查询的字段都是索引字段,就不同回表查询,这样效率高
MyISAM
表结构文件:.frm
索引文件:.MYI
数据文件:.MYD
非聚集索引:叶子节点储存行的内存地址 key:索引字段值 value:行牛内存地址
B+树相对于B树区别:
mysql有page的概念,一个page 16KB ,B+树只有叶子节点会存储行的记录,非叶子节点不储存数据,所以非叶子节点那一层树可以储存更多的节点,并且根节点到叶子节点的查询距离所产生的磁盘IO是均匀的
叶子节点的数据会组成一个链表,这样对于区间查询效率会高很多。
分布式事务
C:强一致性 A:可用性 P:分区容错性
BASE理论 基本可用 软状态 最终一致性
XA 2PC 3PC
TCC
消息最终一致性
客户端
连接器-验证客户端账号对应的权限
查询缓存
SQL解析和预处理
查询优化
执行引擎
inndb
redis 底层数据结构 简单动态字符串SDS
存在失误
16K页 64页(簇/区)extent 逻辑上有关联组成:段Segment
启动ApplicationContext
创建BeanFactory
初始化BeanFactory
执行BeanFactory后置处理器
进行扫描执行BeanFactory后置处理器
生成BeanDefinition
合并父子BeanDefinition
加载类
实例化前
推断构造方法
实例化
BeanDefinition的后置处理器(BeanDefinitionPostProcessor)
填充属性(依赖查找)
执行Aware(InstantiationAwareBeanPostProcessor)
初始化前
初始化
初始化后
Bean销毁
容器关闭
发布ContextClosedEvent事件
调用LifecycleProcessor的onClose方法
销毁单例Bean