1. 程式人生 > >聊聊Java的字節碼

聊聊Java的字節碼

便在 二進制 結果 com 系統 學習 驗證 stat inux

巴山楚水淒涼地,二十三年棄置身。
懷舊空吟聞笛賦,到鄉翻似爛柯人。
沈舟側畔千帆過,病樹前頭萬木春。
今日聽君歌一曲,暫憑杯酒長精神。

一、什麽是Java字節碼?

借用Algorithm(4th)節選:它是程序的一種低級表示,可以運行於Java虛擬機上。將程序抽象成字節碼可以保證Java程序在各種設備上的運行。OK,這個回答可以讓我們回到程序執行上來看下一個問題:

二、程序是怎麽執行的?

學習過計算機的同學都應該深惡痛絕一門課程——編譯原理,這門課程的主要目的就是向你解釋你所見所寫的代碼的執行過程。我們通常使用的C++、Java、python等等都屬於高級計算機語言,但是計算機只能夠理解“0”和“1”也就是二進制機器碼,所以高級程序語言要在機器上執行需要把自己翻譯成二級制機器碼,這個翻譯的過程主要是由編譯器來完成的,例如C++程序編譯後在Windows平臺可以形成.exe的可執行文件,而在Unix或者Linux平臺則會編譯形成.dll文件,不同平臺的C++編譯器是不同的。

三、Java程序是怎麽執行的?

Java要復雜一些,因為Java具有跨平臺特性,為了實現這個特性Java執行在一臺虛擬機上,這臺虛擬機也就是JVM,Java通過JVM屏蔽了不同平臺之間的差異,從而做到一次編譯到處執行。JVM位於Java編譯器和OS平臺之間,Java編譯器只需面向JVM,生成JVM能理解的代碼,這個代碼即字節碼,JVM再將字節碼翻譯成真實機器所能理解的二進制機器碼。

四、字節碼是怎麽產生的?

我們所編寫的程序都是.java格式,通常在執行的時候也許點擊一下eclipse的運行鍵就可以在控制臺看到運行結果,但是也可以更酷一些,如果你裝了JDK,那就可以直接在以命令行的方式編譯運行你的.java文件,編譯後會形成.class文件,這個.class文件即字節碼。

例如:可以用文本新建一個HelloWorld.java文件:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello Java");
    }
}

打開命令行進入文件目錄,輸入編譯命令:javac HelloWorld.java

若程序沒有錯誤,在當前目錄下就會生成同名的HelloWorld.class文件。此時在命令行中輸入java HelloWorld就可以看到程序執行結果: Hello Java

技術分享

為了驗證它的跨平臺特性,我們把.class拿到Windows平臺驗證一下:

技術分享

結果是相同的。

java的命令行功能是很豐富的,不再一一贅述,當然聰明人還是會用一個好的IDE。

五、字節碼怎麽解讀?

字節碼長什麽樣子呢?打開.class文件看看:

技術分享

這就是上面那段HelloWorld的字節碼,的確是以字節形式呈現出來的。四不四看起來頭暈,四不四除了開頭的cafebabe其他都不認識,其實還好啦,你只要知道字節碼就是用字節對應關鍵字,比如開頭的cafebabe對應的就是文件編碼格式,對應表示.class文件的魔數,後面的0034表示版本號。

為什麽要這樣呢?我們再回到第二個問題:程序是怎麽執行的,機器能夠理解的就是二進制機器碼,可是我們編譯器在翻譯的時候不能直接搞成“0”和“1”啊,不然這麽多編程語言,這麽多編譯器,會死人滴,學過計算機基礎的都應該熟悉這樣一張圖(圖片源自百度百科):

技術分享

是的,高級語言轉為機器語言還有一層匯編語言,這是一種符號語言,上手簡單,編寫困難,通常被應用在底層,硬件驅動程序、嵌入式操作系統和實時運行程序都需要匯編語言,也就是說高級語言的編譯器並不是直接將代碼轉成二進制的,二是轉成匯編語言,再通過匯編指令轉成機器碼。回到Java,字節碼其實和匯編語言之間是有對應關系的,當然,字節碼要更豐富一些。

關於字節碼的解讀,不是一兩句話能說清楚的,改天再填坑,如果真的有興趣,可以去看一本書《深入淺出JVM》,有幾個解讀的傳送門如下:

http://blog.csdn.net/dc_726/article/details/7944154/

http://www.importnew.com/13107.html

六、解讀字節碼有什麽意義?

可以讓你明白程序的執行原理,方便在理解後優化代碼,當然,還能幹壞事。。。

聊聊Java的字節碼