编译没学完直接变异了🧬
java源代码文件变成可直接执行的机器指令:java转成class,class转换成机器指令
- java=》字节码打包成jar包
- 字节码执行:一 解释器interpreter即使解释执行,二 jit编译器编译执行
热点代码
方法/代码块频繁允许,jit将部分热点代码class编译机器码 优化后缓存到codeCache
codeCache默认大小2496kb 扩容 最大240M
java9 codeCache三区:减少内存碎片,提高运行效率
- non-method segment存储jvm内部代码,XX:NonNMethodCodeHeapSize配置
- profiled-code segment生命周期短C1编译后的代码XX:ProfiledCodeHeapSize
- non-profiled segment生命周期长C2编译后的代码XX:NonProfiledCodeHeapSize
JIT编译器:client /server
client客户端程序idea等注重应用启动速度,不长使用;C1
server服务端程序spring后端应用,长期驻守 长时间profiling获使用信息;C2
C2编译慢 性能高!
方法内联
编译器 热点代码 字节码大小 <325b 内联 ;非热点代码 方法字节码<35b 内联
方法栈 入栈/出栈 消耗性能:内联 也是一种合并,减少不必要的操作
内联方法多,生成代码执行效率高 / 编译时间长 程序达到性能峰值晚
循环计数器由int改成long,循环展开不会被发送(不会优化减少循环次数)
for int=》 for long X
优化不能低成本处理long溢出情况,启发式安全点检查/全量数组范围检查(降低效率)
安全点
运行到这 表示 对当前代码块内部变量的修改动作done(真的等都执行完了)
就可以代表宇宙授予你安全中断当前线程运行的权力,可进行额外操作:GC内存换代/STW
解释执行:安插字节码之间就行,之间不是之内
编译执行:循环的跳转前/循环完 has check
int类型循环,jvm优化掉前向跳转时安全点,
多线程场景下,如循环非常耗时,出现其他所有线程都到达安全点后 还在等一颗小心心 呸~ 等这一循环线程的情况
外在表现:某一次STW时间特别长 XX:+SafepointTimeout -XX:SafepointTimeoutDelay=1000
安全点检查等待时间超过1000ms jvm打印超时日志
java10临危受命,loop strip mining通profiling统计抵达安全点时间,设计安全点
注意⚠️ 安全点检查的优化 只针对计数循环(可以偷个懒) 其他的非计数都要安插安全点
边界检查消除:
前序循环pre loog
依据步长变化和数组最大长度 推断 不进行边界检查的max循环次数N
N次主循环之后 访问数值带上边界检查 后序循环
逃逸分析
标量替换:没有被外部访问 创建成员变量来替代 不分配内存空间
锁消除:未发生逃逸 可锁消除 去除同步逻辑 提高效率
窥孔优化:编译器后期,局部代码块中的指令 运算强度消减
代码的静态分析得出 依据不同处理器指令集
死代码消除:很简单不说了