《深入理解Java虚拟机》-(实战)boolean类型在虚拟机中是如何处理的

时间:2019-08-13
本文章向大家介绍《深入理解Java虚拟机》-(实战)boolean类型在虚拟机中是如何处理的,主要包括《深入理解Java虚拟机》-(实战)boolean类型在虚拟机中是如何处理的使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

这里先引出Java的8大基本类型。直接上图吧。

可以看到,除了boolean和char类型之外,越往下的类型的值域是包含以上的值域的。因此,从上面的基本类型转换成下面的基本类型,无需强制转换。关于它们的默认值,在内存中保存的都是0。

对于char类型,菜鸟喜鹊有些感悟,就是char类型转成int类型的例子很多。

今天上班忙里抽闲学习了一下"AC自动机"的实现,其中就是模式串构建tired树的时候的char类型处理的时候,直接使用它与'a'相减,得到数组下标的。这里也算是用了一个转换吧。还有String类里的indexOf(int n)也是。

读者有空可以去看看。

对于boolean类型,上图的表格里是true和false的值。可是,从jvm角度来看,可不一样。在这里,你可以参照我上一篇文章写的字节码文章改一下。将值iconst_1改成iconst_3,iconst_4,iconst_5看看有什么结果。再看看我这里的结论。

ok! talk is cheap,show you my code!

(以下操作在linux进行)

1.编写Foo.java

public class Foo {
  static boolean boolValue;
  public static void main(String[] args) {
    boolValue = true; // 将这个 true 替换为 2 或者 3,再看看打印结果
    if (boolValue) System.out.println("Hello, Java!");
    if (boolValue == true) System.out.println("Hello, JVM!");
  }
}

2.编译运行

[root@localhost tmp2]# javac Foo.java
[root@localhost tmp2]# java Foo
Hello, Java!
Hello, JVM!

3.查看class字节码(这里就不看了,就看boolValue的值就好了。上一篇文章中有演示过(https://www.cnblogs.com/chenscript/p/11343270.html))

4.修改常量值分别为4和5,编译并输出结果:

[root@localhost tmp2]# awk 'NR==1,/iconst_1/{sub(/iconst_1/,"iconst_4")} 1' Foo.jasm.1>Foo.jasm
[root@localhost tmp2]# java -jar ../asmtools.jar jasm Foo.jasm
[root@localhost tmp2]# java Foo
(改成4的时候,没有输出!) [root@localhost tmp2]# awk
'NR==1,/iconst_1/{sub(/iconst_1/,"iconst_5")} 1' Foo.jasm.1>Foo.jasm [root@localhost tmp2]# java -jar ../asmtools.jar jasm Foo.jasm [root@localhost tmp2]# java Foo Hello, Java! Hello, JVM!

这里,我们就该查看一下字节码:

5.这里就贴关键部分的字节码吧。

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: iconst_4                           //
         1: putstatic     #5                  // Field boolValue:Z
         4: getstatic     #5                  // Field boolValue:Z
         7: ifeq          18
        10: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
        13: ldc           #2                  // String Hello, Java!
        15: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        18: getstatic     #5                  // Field boolValue:Z
        21: iconst_1   //
        22: if_icmpne     33
        25: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
        28: ldc           #1                  // String Hello, JVM!
        30: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        33: return
      StackMapTable: number_of_entries = 2
        frame_type = 18 /* same */
        frame_type = 14 /* same */
  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: iconst_5                           //
         1: putstatic     #5                  // Field boolValue:Z
         4: getstatic     #5                  // Field boolValue:Z
         7: ifeq          18
        10: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
        13: ldc           #2                  // String Hello, Java!
        15: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        18: getstatic     #5                  // Field boolValue:Z
        21: iconst_1   //
        22: if_icmpne     33
        25: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
        28: ldc           #1                  // String Hello, JVM!
        30: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        33: return
      StackMapTable: number_of_entries = 2
        frame_type = 18 /* same */
        frame_type = 14 /* same */

总结上面的输出:

如果单从肉眼看,按照上一篇的学习,改写成4和5的时候,ifeq比较的值是0,0与4、5怎么可能匹配得上?但是在改成iconst_5的时候,虚拟机就判断是不相等,然后输出“Hello,Java”,改成4的时候,就相等,直接跳转。

为什么呢?

这里面是有点玄机。

根据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.

官方说:

布尔类型:布尔数据类型只有两个可能的值:真和假。使用此数据类型为跟踪真/假条件的简单标记。这种数据类型就表示这一点信息,但是它的“大小”并不是精确定义的。

由于笔者实力有限,也只能到这一步了。但根据实际操作看推测的话,这个二进制有关,也就是比较的值都是使用二进制的最低位进行比较的。也就是,4的二进制100,5 的二进制是101,取最低位,就是0和1了。这里机器码中的0是false,1是true~就这样吧~

 

 

Java基本类型在局部变量区(属于Java方法栈)和堆中的存储大小是有区别的:

主要表现于:boolean、byte、char、short 这几个的存储大小根据环境不同而不同

局部变量区:在32位的hotspot中都是占用4个字节,而在64位的hotspot中占用8个字节。

堆:byte、char、short分别占一字节、两字节、两字节。(也就是跟这些的值域相吻合的~~)

 

以上~

$flag 上一页 下一页