1Java代码怎么运行的
为什么在虚拟机里运行?
- 高级语言语法复杂,抽象程度高,不能直接在硬件上运行(需转换成java字节码)。
Java字节码指令的操作码(opcode)被固定为一个字节,所以取名java字节码 - 虚拟机带来了另一个好处:托管环境,可处理内存管理、垃圾回收,数组越界检查、动态类型、安全权限的动态检查,聚焦于业务代码处理。
Java虚拟机具体是怎样运行Java字节码的?
JVM内存模型
5部分
- 方法区
JVM加载class文件到方法区 - 堆
- 线程私有区域
- 线程方法栈
- 本地方法栈
- PC寄存器(计数器) 存放线程执行位置(线程执行的字节码指令地址)
解释执行/编译执行
HotSpot为例,JVM需将方法去的字节码文件转换为机器码文件,两种方式
- 解释执行
逐条将字节码翻译为机器码并执行 - 即时编译
将方法中所有字节码编译成机器码后执行
解释执行快不需等待,即时编译实际运行速度快。HotSpot默认采用混合模式,结合两者有点,先解释执行字节码,后将热点代码以方法为代码即时编译。
Java虚拟机的运行效率究竟是怎么样的?
HotSpot JVM采用多技术提升启动性能及峰值性能,重要手段:即时编译。
20%代码占用80%计算资源,二八原则。80%不常用代码采用解释执行,20%热点代码即时编译。
HotSpot内置多个即时编译器:C1 、C2 、 Graal
在编译时间和生成代码的执行效率取舍
- C1 Client编译器
优化手段简,编译快,启动快,面向客户端程序 - C2 Server编译器
优化手段复杂,编译较慢,但生成代码执行效率高。面向对峰值性能有要求的服务器端程序。
JAVA7开始HosPot默认采用分次编译:热点代码首先C1编译,之后热点中的热点C2编译
HosPot即时编译在额外的编译线程中进行,为了不干扰应用正常运行。根据CPU数目设置线程数,按1:2配置C1、C2
计算资源充足的情况下,解释执行和编译执行同时进行,下次调用该方法时替换解释执行。
即时编译器因为有程序的运行时信息,优化效果更好,代码效率更高,程序峰值性更好
思考题
对于发布不频繁程序,运行时性能要求高,为什么不全部编译成机器码呢?
- AOT能够在线下将Java字节码编译成机器码,主要是用来解决启动性能不好的问题。
- 对于发布不频繁(也就是长时间运行吧?)的程序,选择线下编译和即时编译一样,因为至多一两个小时即时编译就完成了。
- 即时编译器有根据运行时信息优化,效果更好,峰值性能更好
- 线下编译和即时编译在峰值性能差不多的这个前提下,线下编译和即时编译就是两种选项,各有优缺点。JVM这样做,主要也是看重字节码的可移植性,而牺牲了启动性能。