点击上方“朱小厮的博客”,选择“设为星标”

后台回复"书",获取

后台回复“k8s”,可领取k8s资料

来源:r6d.cn/ZxLw

这是Java字节码上针对字节码大小的一个早期优化。从现在的角度看它可能算是一种过早优化(premature optimization)了。

Java字节码指令集里,大部分跟局部变量打交道的指令(例如<type>load、<type>store)都有完整版:

<type>load n

例如iload 5,以及针对头4个局部变量/参数的缩写版:

<type>load_<n>

例如iload_0,这样两个版本。其中,缩写版,正如标题所说,只有0~3的范围。

它们的区别是,前者有显式的“操作数”(operand),而后者是把操作数融合到了操作码(opcode)里面。看iload与iload_<n>的例子就很清楚:

iload的指令格式是:Chapter 6. The Java Virtual Machine Instruction Set[1]

iload index

其中"iload"是opcode,其值为21(0x15),而后面跟着一个unsigned byte作为index来指定局部变量的下标。另外还有wide版,如果在iload前面带有wide前缀的话,则格式为:

wide iload index1 index2

其中wide、iload、index1、index2各自为一个字节,而 (index1 << 8) | index2 构成指令局部变量下标的操作数。

iload_的指令格式则是:Chapter 6. The Java Virtual Machine Instruction Set[2]

iload_<n>

其中iload_<n>自身就是opcode,它可能的取值为:iload_0 = 26 (0x1a)iload_1 = 27 (0x1b)iload_2 = 28 (0x1c)iload_3 = 29 (0x1d)这样的话,针对头4个局部变量,iload_<n>就可以只用一个字节的opcode来表达整条指令,比使用完整版的iload要少一个字节。使用缩写版指令不但可以让字节码的大小减少,还可以让解释器(注意!只是解释器)的性能提升。因为解释器通常都会有这样的结构:

while (true) {opcode = *program_counter++;    // fetch opcode://   1 memory read, 1 memory writeswitch (opcode) {               // dispatch opcodecase some_instruction:operands = decode_operands(); // decode operands://   1~n memory readsperform_operation(operands);  // actual operationprogram_counter += size_of_some_instruction; // 1 memory read, 1 memory writebreak;}
}

(解释器有各种优化方式,上面的形式是最简单的switch-threading,但 fetch-dispatch/decode-execute 的组成部分总是存在的)当使用缩写版指令时,decode_operands()就不需要做任何额外的内存读,因为operand已经隐藏在opcode里了,于是就会比完整版指令要快一些。

至于为啥选择0~3的范围来做缩短版,我不知道当初JVM原始设计的过程中具体发生了怎样的讨论和设计取舍,但一种可以想像的可能性是:最初的JVM的解释器已经写好了,看看1个字节的opcode能表达的256个opcode中已经用了多少个,然后再想想剩下的空余的那些可以用来做怎样的局部优化。

大概是正好发现,如果用0~3的话可以基本上把opcode范围用满(JVM规范里使用了的opcode范围比Sun最初的JVM内部所使用的opcode范围要小一些,因为Sun JVM使用了一些quick_系字节码并没有作为规范的一部分,而是在第一版JVM规范里作为额外的讲解说剩余的编码空间可以用来做quick_系指令的优化),如果用例如说0~4的话就把1字节opcode编码空间用超了,而0~2的话则用不满。

就这样而已。

于是早期的坊间传说的Java程序性能优化指引中,有一条是说:Java方法应该尽量只使用不超过4个参数+局部变量,最频繁使用的局部变量应该放在前面,来想办法使用上Java字节码的这个缩写版指令优化。

然而后来JIT编译器成为主流后,这种优化指引就完全没有用了。JIT编译器根本不在乎输入的字节码是完整版还是缩写版,都一样对待。

参考资料

[1]

Chapter 6. The Java Virtual Machine Instruction Set: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.iload

[2]

Chapter 6. The Java Virtual Machine Instruction Set: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.iload_n

想知道更多?描下面的二维码关注我

后台回复"技术",加入技术群

后台回复“k8s”,可领取k8s资料

【精彩推荐】

  • 原创|OpenAPI标准规范

  • 中台不是万能药,关于中台的思考和尝试

  • ClickHouse到底是什么?为什么如此牛逼!

  • 原来ElasticSearch还可以这么理解

  • 面试官:InnoDB中一棵B+树可以存放多少行数据?

  • 微服务下如何解耦?对于已经紧耦合下如何重构?

  • 如何构建一套高性能、高可用、低成本的视频处理系统?

  • 架构之道:分离业务逻辑和技术细节

  • 星巴克不使用两阶段提交

点个赞+在看,少个 bug ????

JAVA字节码指令iload_n为什么只有0到3?相关推荐

  1. java字节码指令简介(仅了解)

    [0]README 0.1)本文全文转自 "深入理解jvm", 旨在了解 java字节码指令 的基础知识: [1]写在前面 1)由于jvm 采用面向操作数栈而不是寄存器的结构,所以 ...

  2. 【JVM源码解析】模板解释器解释执行Java字节码指令(上)

    本文由HeapDump性能社区首席讲师鸠摩(马智)授权整理发布 第17章-x86-64寄存器 不同的CPU都能够解释的机器语言的体系称为指令集架构(ISA,Instruction Set Archit ...

  3. 常见 Java 字节码 指令 助记符

    转自: 常见java字节码 有时候为了能理解JVM对程序所做的优化等,需要查看程序的字节码,因此知道了解一些常见的指令集很重要! 指令码 助记符 说明 0x00 nop 什么都不做 0x01 acon ...

  4. Java字节码指令简介

    本文是<深入理解Java虚拟机>中第六章的读书笔记. 1.概述 在Class文件中,Java方法里的方法体,也就是代表着一个Java源码程序中程序的部分存储在方法表集合的Code属性中.存 ...

  5. Java字节码指令大全

    Java二进制指令代码解析 Java源码在运行之前都要编译成为字节码格式(如.class文件),然后由ClassLoader将字节码载入运行.在字节码文件中,指令代码只是其中的一部分,里面还记录了字节 ...

  6. java 数字表示什么意思是什么,读取Java字节码指令:数字是什么意思?

    Java类文件和字节码 Java类文件(字节码文件)由不同的组件组成: >幻数:0xCAFEBABE >类文件格式的版本:类文件的次要版本和主要版本 >常量池:类的常量池 >( ...

  7. JVM笔记:Java虚拟机的字节码指令详解

    1.字节码 Java能发展到现在,其"一次编译,多处运行"的功能功不可没,这里最主要的功劳就是JVM和字节码了,在不同平台和操作系统上根据JVM规范的定制JVM可以运行相同字节码( ...

  8. Java虚拟机字节码指令

    Java字节码指令 Java 字节码指令及javap 使用说明 ### java字节码指令列表 字节码 助记符 指令含义 0x00 nop 什么都不做 0x01 aconst_null 将null推送 ...

  9. java字节码运行原理_JVM 内部原理(六)— Java 字节码基础之一

    JVM 内部原理(六)- Java 字节码基础之一 介绍 版本:Java SE 7 为什么需要了解 Java 字节码? 无论你是一名 Java 开发者.架构师.CxO 还是智能手机的普通用户,Java ...

最新文章

  1. html 多项选择,选项标签中的HTML多字段选择
  2. WCF-Discovery的协议基础:WS-Disvovery(客户端驱动探测服务)
  3. 2、django管理网站
  4. SLF4J和log4j的整合使用
  5. ios realm 文件_iOS Realm数据库使用
  6. 幻想英雄2-战神再起折扣号新手入门攻略
  7. mysql 强项_mysql数据目录迁移
  8. mysql重复你数据标识_MySQL 处理重复数据
  9. 压箱底的Android UI开源库(一)
  10. 深入浅出MYSQL查询索引失效
  11. 带你玩转IntelliJ IDEA 使用教程(2019图文版)
  12. Redis过期策略详解
  13. WebDriver与浏览器版本对应关系
  14. HCK哈士奇x可口可乐联名潮酷冰吧,你还没入手吗?
  15. 宏碁 Acer AS4738ZG-P622G32Mncc 驱动
  16. 同是匿名社交,国内外“秘密”大不同
  17. 云计算采用的各种虚拟化技术比较
  18. 阿里云第二次实验——个人网盘的搭建
  19. vue移动端网页适配
  20. Java学习---Linux总结

热门文章

  1. 第四单元用计算机写作,计算机复习题
  2. d3中文案例_D3.js柱状图例子
  3. Java 中,类、类对象、泛型之间的转换
  4. Django 2 零基础 - 待办清单网站
  5. 在EO中获取某字段基于表的列名
  6. hdu1160 dp
  7. 【C++】const成员函数
  8. [学习笔记]Hadoop 配置调试错误收集
  9. 个人遇到局域网不能访问解决分享
  10. CodeForces - 1327D Infinite Path(图论综合)