最近在系統(tǒng)回顧學(xué)習(xí) Java 虛擬機(jī)方面的知識(shí)疾捍,其中想到一個(gè)很有意思的問(wèn)題:布爾型在虛擬機(jī)中到底是什么類型奈辰?
要想解答這個(gè)問(wèn)題,我們看 JDK 的源碼是無(wú)法解決源碼的乱豆,我們必須深入到 class 文件中才能解決問(wèn)題奖恰。于是他給出了這么一道題:
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!");
}
}
}
這道題很簡(jiǎn)單,結(jié)果是輸出:
Hello, Java!
Hello, JVM!
但我們要深入到 class 文件中去看看 JVM 對(duì)于這段代碼,它到底是怎么執(zhí)行字節(jié)碼指令的瑟啃。于是我們使用 javac 命令得到它的 class 字節(jié)碼文件:
javac Foo.java
字節(jié)碼文件都是十六進(jìn)制的字符集合论泛,我們一般可以用 javap 命令來(lái)實(shí)現(xiàn)反匯編工作。但這次我們使用另一個(gè)工具蛹屿,即 asmtools屁奏。它是 OpenJDK 提供的另一個(gè)反匯編工具。
java -cp /path/to/asmtools.jar org.openjdk.asmtools.jdis.Main Foo.class > Foo.jasm.1
注:上面需要下載 asmtools 這個(gè) Jar 包错负,下載地址:asmtools - Code Tools - OpenJDK Wiki
上面這行命令其實(shí)就是把字節(jié)碼文件反匯編一下坟瓢,然后存在 Foo.jasm.1 文件里。我們打開(kāi) Foo.jasm.1 文件可以看到下面的內(nèi)容:
其實(shí)這個(gè)文件就是一系列字節(jié)碼指令的集合犹撒,上面 main 方法中的字節(jié)碼指令我們可以分兩部分來(lái)看载绿。接下來(lái)我們一部分一部分來(lái)分析:
(放大圖片查看每個(gè)指令集的作用)
其實(shí)這幾行的邏輯對(duì)應(yīng)下面這塊源碼:
if(flag){
System.out.println("Hello, Java!");
}
而第二部分的字節(jié)碼指令的分析:
(放大圖片查看每個(gè)指令集的作用)
這幾行的邏輯對(duì)應(yīng)下面這塊源碼:
if(flag == true){
System.out.println("Hello, JVM!");
}
經(jīng)過(guò)這么一分析,你會(huì)發(fā)現(xiàn)在 Java 虛擬機(jī)中是不存在布爾值這一類型的油航,他們都被整型來(lái)替代了。
其實(shí)還有一個(gè)方法可以很直觀地看出布爾型是使用整型表示的怀浆,那就是將 Foo.jasm 文件恢復(fù)成 class 文件谊囚。運(yùn)行下面的命令,將其恢復(fù)成 class 文件:
java -cp asmtools.jar org.openjdk.asmtools.jasm.Main Foo.jasm
你會(huì)發(fā)現(xiàn)目錄下生成了一個(gè) Foo.class 文件执赡,我們使用 JD-GUI 工具打開(kāi)它:
你會(huì)發(fā)現(xiàn)原來(lái)是布爾型的變量镰踏,現(xiàn)在變成了整型。原來(lái)的 true 現(xiàn)在是 1 了沙合。
總結(jié)一下奠伪,其實(shí)布爾型在 Java 虛擬機(jī)是用整型表示的,true 用 1 表示首懈,false 用 0 表示绊率。