在阅读JVM规范时(就像我一样),当我遇到7个iconst_<i>操作码时,我感到非常惊讶.毕竟,只有一个字节可以播放.
我很少在代码中写入2,3,4或5的文字.我可以理解为什么-1,0和1可能会被特别对待,但我觉得设计师想要将4个珍贵的操作码吹到恰好相当小的数字上似乎很神奇.
有谁知道这是否有充分理由?我低估了这些的好处吗?
我认为,您的假设是正确的:只是为了使字节码更小而Java解释器稍微快一点(那些时候没有JIT编译器)。请注意,这些字节码的使用频率可能比您期望的要高得多。例如,考虑以下代码:
int[] a = {10, 20, 30, 40};
Run Code Online (Sandbox Code Playgroud)
有效地将其编译为以下内容:
int[] a = new int[4];
a[0] = 10;
a[1] = 20;
a[2] = 30;
a[3] = 40;
Run Code Online (Sandbox Code Playgroud)
因此iconst_0,iconst_4即使您在源代码中没有这样的常量,也可以使用这里to 。
希望这可以澄清你的问题为什么浪费 4 个操作码..
查看此代码的字节码
public static void main(String[] args) {
int b = 20;
int c = 5;
int d= 6;
}
Run Code Online (Sandbox Code Playgroud)
字节码的一部分
0: bipush 20
2: istore_1
3: iconst_5
4: istore_2
5: bipush 6
7: istore_3
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,对于大于 5 的数字,它开始使用的bipush效率通常低于等效数字iconst_<n>,并且还会占用类文件中更多的字节。
bipush
byte1扩展byte1为 int 然后将其压入堆栈,因为 Java 堆栈上的每个槽都是 32 位宽(JVM 是基于堆栈的虚拟机)
并查看是否bipush占用更多字节..
查看以下两个代码的类文件大小。(这个大小是在我的 64 位机器上。在您的机器上可能有所不同,但差异是相同的)
public class Test2 {
public static void main(String[] args) {
int b = 5;
}
}
Run Code Online (Sandbox Code Playgroud)
大小 406 字节
现在如果我更换b =6;同一类文件的大小变得407 bytes保持不变,直到即使当b=127它也使用bipush. 这种大小差异是由于 bipush 有 2 个字节,一个字节操作码,第二个字节立即常量值
双推格式:
bipush
byte
Run Code Online (Sandbox Code Playgroud)
正如您从5: bipush 6字节码中的行所看到的, whileiconst_<n>仅使用 1 个字节。
所以针对一些常用的压入的数字定义了这样的字节码,以提高字节码执行效率并减少字节码流的大小。
正如塔吉尔所说,这些数字的使用频率比你想象的要高
| 归档时间: |
|
| 查看次数: |
648 次 |
| 最近记录: |