这是一段代码
public class Classifier {
public static void main(String[] args)
{
Integer x = -127;//this uses bipush
Integer y = 127;//this use bipush
Integer z= -129;//this use sipush
Integer p=32767;//maximum range of short still sipush
Integer a = 128; // use sipush
Integer b = 129786;// invokes virtual method to get Integer class
}
}
这是部分字节码
stack=1, locals=7, args_size=1
0: bipush -127
2: invokestatic #16 // Method java/lang/Integer.valueO
f:(I)Ljava/lang/Integer;
5: astore_1
6: bipush 127
8: invokestatic #16 // Method java/lang/Integer.valueO
f:(I)Ljava/lang/Integer;
11: astore_2
12: sipush -129
15: invokestatic #16 // Method java/lang/Integer.valueO
f:(I)Ljava/lang/Integer;
18: astore_3
19: sipush 32767
22: invokestatic #16 // Method java/lang/Integer.valueO
f:(I)Ljava/lang/Integer;
25: astore 4
27: sipush 128
30: invokestatic #16 // Method java/lang/Integer.valueO
f:(I)Ljava/lang/Integer;
33: astore 5
35: ldc #22 // int 129786
37: invokestatic #16 // Method java/lang/Integer.valueO
f:(I)Ljava/lang/Integer;
40: astore 6
42: return
正如我看到的,对于 -128 到 127
之间的整数范围,它使用 bipush
将一个字节作为整数值压入堆栈。
在 -32768 到 32767
范围内,它使用 short
作为 sipush
的包装类。接下来它使用整数。什么 JVM 使用 byte 和 short 来存储 Integer 值?
最佳答案
它在运行时不存储为byte
或short
,只是在字节码中。
假设您要将值 120
存储到 Integer
中。您编写了编译器,因此您解析了源代码,并且您知道常量值 120
可以放入一个带符号的字节中。因为您不想在字节码中浪费空间来将值 120
存储为 32 位(4 字节)值,如果它可以存储为 8 位(1 字节),您将创建特殊指令,即将只能从方法字节码加载一个 byte
并将其作为 32 位 integer
存储在堆栈中。这意味着,在运行时,您确实拥有 integer
数据类型。
与在任何地方使用 ldc
相比,生成的代码更小更快,后者需要与 jvm 进行更多交互,因为需要使用运行时常量池进行操作。
bipush
有 2 个字节,一个字节操作码,第二个字节立即常量值。因为您只有一个字节用于值,所以它可用于 -128 到 127 之间的值。
sipush
有3个字节,一个字节的操作码,第二个和第三个字节立即数
常数值。
bipush 格式:
bipush
byte
sipush格式:
sipush
byte1
byte2
关于java - 为什么在 JVM 中 Integer 存储为 byte 和 short?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29875430/