您当前的位置: 首页 >  Java

星拱北辰

暂无认证

  • 0浏览

    0关注

    1205博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

【JVM】javap命令行分析揭示boolean的本质的虚拟机指令

星拱北辰 发布时间:2020-03-03 10:59:07 ,浏览量:0

源代码
public class BooleanTest {
    public static void main(String[] args) {
        boolean a = true;
        boolean b = false;
        System.out.println(a);
        System.out.println(b);
    }
}
编译
>javac BooleanTest.java
执行
>java BooleanTest
true
false
反汇编
>javap -c BooleanTest
Compiled from "BooleanTest.java"
public class BooleanTest {
  public BooleanTest();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_1
       1: istore_1
       2: iconst_0
       3: istore_2
       4: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       7: iload_1
       8: invokevirtual #3                  // Method java/io/PrintStream.println:(Z)V
      11: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      14: iload_2
      15: invokevirtual #3                  // Method java/io/PrintStream.println:(Z)V
      18: return
}
main()的虚拟机指令分析
iconst_1

上面的指令表示先生成一个常量,值为1,实际上是true。

istore_1

上面的指令表示将常量1赋值给第一个变量(在jshell里就是$1)

iconst_0

上面的指令表示先生成一个常量,值为0,实际上是false。

istore_2

上面的指令表示将常量0赋值给第二个变量(在jshell里就是$2)

getstatic

由于System.out.println()其中的System.out其实是java.lang.System中的一个静态的属性,所以这个指令顾名思义,就是获取这样一个静态属性。 这个System.out的类型其实是java.io.PrintStream,这点我们在之前的文章中也说过了,感兴趣的可以查看源码自行了解。

iload_1

将$1压栈,加到虚拟机栈空间中。

invokevirtual

调用System.out的println(),打印$1的值,输出true。

getstatic

再次获取System.out

iload_2

将$2压栈,加到虚拟机栈空间中。

invokevirtual

调用System.out的println(),打印$2的值,输出false。

return

main()返回值为void,使用return结束方法,相当于C/C++中int main()最后的return 0。

深入探讨boolean字节数

引自——http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html的说明:

boolean: The boolean data type has only two possible values: true and false. Use this data type for simple flags that track true/false conditions. This data type represents one bit of information, but its “size” isn’t something that’s precisely defined.

【翻译】 布尔值:布尔数据类型只有两个可能的值:true和false。 将此数据类型用于跟踪真/假条件的简单标志。 此数据类型代表一小部分信息,但其“大小”并不是精确定义的。

其实学过C语言的大家也知道,C中没有boolean/bool这种类型的变量,只需要使用0/1即可,经过测试我们也知道,哪有boolean这种东西啊?计算机中所有的运算都是0/1序列,怎么存在真正的boolean?

同样的,既然本身不存在,那其占用空间与实现方式有关,而实现方式由编译器、虚拟机等决定。

《Java虚拟机规范》书中说到: 虽然定义了boolean这种数据类型,但是只对它提供了非常有限的支持。在Java虚拟机中没有任何供boolean值专用的字节码指令,Java语言表达式所操作的boolean值,在编译之后都使用Java虚拟机中的int数据类型来代替,而boolean数组将会被编码成Java虚拟机的byte数组,每个元素boolean元素占8位。

结论
  1. boolean类型实际不存在,在JVM中使用0/1表示false/true。
  2. boolean类型占用字节数没有被规定,这与编译器、虚拟机等有关。
  3. boolean类型在规范标准的虚拟机中占4个字节;但规定boolean数组中每一个boolean使用1个字节的byte表示以节约空间。(所以说,网传1字节特别是1bit的,基本认定是骗人的)
再思考:4字节/1字节?

Java有四种整数类型,byte(1 bit)、short(2 bits)、int(4 bits)、long(8 bits)。

已知boolean就是使用0/1整数表示的前提下,使用byte表示boolean可以节约空间,这对于长数组或者大规模多维数组来说还是挺重要的。

而使用int表示普通boolean,看似消耗了更多的空间,但实际上考虑到在32位/64位的机器上进行运算,int显然更方便一些,对计算本身很友好。

这种选择正是体现了计算机科学中的“Trade Off”,我在很多文章里都提到过,很orz这个词。我们还是要在不完美中选择最适合具体情况的最优解啊orz。

关注
打赏
1660750074
查看更多评论
立即登录/注册

微信扫码登录

0.0612s