從字節碼層面,解析 Java 布爾型的實現原理

最近在系統回顧學習 Java 虛擬機方面的知識,其中想到一個很有意思的問題:布爾型在虛擬機中到底是什麼類型?

要想解答這個問題,我們看 JDK 的源碼是無法解決源碼的,我們必須深入到 class 文件中才能解決問題。於是他給出了這麼一道題:

public class Foo{

static boolean flag;

public static void main(String[] args){

flag = true;

if(flag){

System.out.println("Hello, Java!");

}

if(flag == true){

System.out.println("Hello, JVM!");

}

}

}

這道題很簡單,結果是輸出:

Hello, Java!

Hello, JVM!

但我們要深入到 class 文件中去看看 JVM 對於這段代碼,它到底是怎麼執行字節碼指令的。於是我們使用 javac 命令得到它的 class 字節碼文件:

javac Foo.java

字節碼文件都是十六進制的字符集合,我們一般可以用 javap 命令來實現反彙編工作。但這次我們使用另一個工具,即 asmtools。它是 OpenJDK 提供的另一個反彙編工具。

java -cp /path/to/asmtools.jar org.openjdk.asmtools.jdis.Main Foo.class > Foo.jasm.1

注:上面需要下載 asmtools 這個 Jar 包,下載地址:asmtools - Code Tools - OpenJDK Wiki

上面這行命令其實就是把字節碼文件反彙編一下,然後存在 Foo.jasm.1 文件裡。我們打開 Foo.jasm.1 文件可以看到下面的內容:

從字節碼層面,解析 Java 布爾型的實現原理

其實這個文件就是一系列字節碼指令的集合,上面 main 方法中的字節碼指令我們可以分兩部分來看。接下來我們一部分一部分來分析:

從字節碼層面,解析 Java 布爾型的實現原理

(放大圖片查看每個指令集的作用)

其實這幾行的邏輯對應下面這塊源碼:

if(flag){

System.out.println("Hello, Java!");

}

而第二部分的字節碼指令的分析:

從字節碼層面,解析 Java 布爾型的實現原理

(放大圖片查看每個指令集的作用)

這幾行的邏輯對應下面這塊源碼:

if(flag == true){

System.out.println("Hello, JVM!");

}

經過這麼一分析,你會發現在 Java 虛擬機中是不存在布爾值這一類型的,他們都被整型來替代了。

其實還有一個方法可以很直觀地看出布爾型是使用整型表示的,那就是將 Foo.jasm 文件恢復成 class 文件。運行下面的命令,將其恢復成 class 文件:

java -cp asmtools.jar org.openjdk.asmtools.jasm.Main Foo.jasm

你會發現目錄下生成了一個 Foo.class 文件,我們使用 JD-GUI 工具打開它:

從字節碼層面,解析 Java 布爾型的實現原理

你會發現原來是布爾型的變量,現在變成了整型。原來的 true 現在是 1 了。

總結一下,其實布爾型在 Java 虛擬機是用整型表示的,true 用 1 表示,false 用 0 表示。


分享到:


相關文章: