深入理解JVM读书笔记——自适应代码生成

笔记书籍:JRockit权威指南深入理解JVM

作者:马库斯.希尔特 马库斯.拉杰格伦 著
翻译:曹旭东

2.1 JAVA虚拟机

JVM将字节码转化为匹配当前硬件架构的本地代码供CPU执行。具体以两种实现方式:
1 JVM规范将JVM描述为一个状态机器,因此实际上并不需要真的将字节码转化为本地代码执行 。JVM可以完整模拟Java程序的 执行状态。例如可以将每条字节码模拟为一个JVM状态函数。这种方式称为字节码解释执行(bytecode interpretation),在这种情况下,唯一直接执行的本地代码(这里暂不考虑JNI)就是JVM本身。
2 JVM将字节码编译为匹配目标平台的本地代码,然后再调用执行这些本地代码。一般情况下 ,将字节码编译为本地代码这一步发生在某个方法第一次被调用的时候。这个过程就是众所周知的即时编译(Just-In-Time compilation,也叫JIT编译)

2.1.1 基于栈的虚拟机

JVM是一种基于栈的虚拟机,绝大部分字节码操作都是处理操作数栈的内容,从栈中弹出内容,计算,再将结果放回栈中。
除了操作数栈 之外 ,按照字节码的格式,还有多达65536个寄存器可以使用。寄存器也称为局部变量(local variable)
在字节码格式中,操作指令都被编译在 一个字节中 ,也就是说,Java最多支持256种操作码(opcode),每种操作都对应着一个唯一值和类似于汇编指令 的助记符(mnemonic)。

2.1.2 字节码格式

1 操作与操作数
每种操作都使用一个字节表示,后跟一个可选的、长度可变的操作数。
一般情况下,带有操作数的字节码指令的长度不会超过3字节。
返回值为boolean类型时是使用常量整数来表示的 。
2 常量池
对于字节码程序来说,常用的操作数会内嵌于字节码指令中。
较大块的数据,例如常量字符串,比较大的数字,是 存储在.class文件开始部分的常量池中。当使用这类数据作为操作数时,使用的是常量池中数据的索引位置,而不是实际数据本身。
此外,Java程序中的方法、属性和类的元数据等也作为.class文件的组成部分,存储在常量池中。

2.2代码生成策略

jvm执行字节码指令时有几种不同的方式
在这里插入图片描述

2.3自适应代码生成

由以上知识点总结结论:
1 代码生成是在运行过程中进行,而不是预先完成。
2 代码生成器应该区分热方法 和冷方法。不应将过多的资源和效率浪费在冷方法上
3 自适应运行时的JIT编译器需要记录一些额外的信息来确保在必要时刻能够重新生成本地代码。
代码执行效率公式:
总体执行时间=代码生成时间+代码执行时间

2.3.1判断热方法

在这里插入图片描述

2.3.2优化动态程序

在汇编语言,call指令完成方法调用。
在面向对象中,虚拟方法分派通常被编译为对分派表中地址的间接调用(indirect call,即需要从内存中读取真正的调用地址)
这句话的意思是每个类都有给一个分派表,其中包含了其虚拟调用的接收者信息,根据不同 的类继承结构,分派虚拟 调用时可能会有多个接收者。
静态方法和确只只有一个接收者的虚拟方法可以被编译为对固定调用地址的直接调用。
优化策略——“赌”
若是“赌”,则需要以下几点典型假设:
1 虚拟方法不会被覆盖。由于某个虚拟方法只存在一种实现,则其可以优化为直接调用
2 浮点数的值永远不会是NaN。大部分情况下,可以使用硬件指令来替换对本地浮点数函数库的调用。
3 某些try语句块不会抛异常,可以将catch语句中的代码 作为冷方法对待。
4 对于大多数三角函数,硬件指令fsin都能达到精度,若达不到则调用本地浮点函数库。
5 锁竞争初期不会太激烈则使用自旋锁来替代。
6 锁可能会周期性地被同一个线程获取和释放,所以,可以将对锁的重复获取操作和重复释放操作直接省略。

2.4深入JIT编译器

本节介绍JIT编译器如何将字节码编译为高效的本地代码。
在这里插入图片描述
博主提示:在总结JIT如何高效编译为本地代码中,作者并未对内容进行详细讲述。后续笔记会细细剖析。

2.5代码流水线

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值