程序員想知道代碼是怎樣跑起來的

程序員使用Java語言實現累加求和的方法,將文件命名爲Sample.java。java

public class Sample {
    public static void main(String[] args) {
        System.out.println(sum(10));
    }

    private static int sum(int n) {
        int res = 0;
        for (int i = 1; i < n; i++) {
            res += i;
        }
        return res;
    }
}

程序員不想直接點擊運行,使用javac編譯了Sample.java文件,能夠看到Sample.java所在的目錄下,生成了Sample.class文件。程序員

那要是彙編語言,具體步驟應該是怎樣的啊?算法

不過,什麼是彙編語言?彙編語言其實和硬件息息相關,也就是脫離不了實際的硬件環境,沒法跨平臺運行,由於彙編語言是人們用助記符表述CPU的動做。CPU結構不同,彙編語言調用的可能也不同。編程

那助記符是什麼意思呢?彙編語言的每一行,表示對CPU的一個指令,其語法結構是操做碼 + 操做數。固然也存在只有操做碼,例如ret,表示將處理返回到函數的調用源。segmentfault

操做碼是對CPU的指令,是動詞,那操做碼是數據,是存儲在CPU的寄存器,是賓語。如mov a b; 表示將b的值賦值給a;add a b; 表示a同b的值相加,並將結果賦值給a。windows

那CPU是否是直接能懂這些助記符嗎?固然不能。微信

咱們知道計算上全部的地址和數據都是由0和1組成的,將彙編語言的那些助記符寫在文本文件上,進行編譯的時候會調用本地計算機上的應用,名爲masm.exe,是一個編譯器。編程語言

將文本文件編譯成目標文件,此時的目標文件成了機器語言,能夠直接被本地的CPU所理解的,若是將這個目標文件由別的計算機的不一樣系列CPU理解,那多是讀不懂,就比如如咱們看不懂火星文。函數

那這個目標文件能夠被本地CPU能夠直接解析運行了嗎?能夠是能夠,可是會直接被報錯。優化

由於咱們僅有這一個目標文件,還不知道這個目標文件和系統的庫文件哪些有關。因此,須要一個連接器,把相關的目標文件組合成一個能夠在特定平臺運行的可執行文件,以下圖:

彙編語言

庫文件名的後綴也是.O或 .OBJ。其中, .ASM .OBJ和 .EXE是在dos或windows系統下的文件, .S和 *.O是在以Linux內核的系統下的文件後綴名,不過Linux內核不靠文件後綴名來判斷這是什麼文件,通常靠文件屬性來判斷,可執行文件在Linux內核中沒有後綴名,用ls命令顯示這個文件是綠色就是可執行文件。

好了,若是是C/C++語言,它的編譯過程應該是怎麼樣子的呢?

C語言編譯器過程

預處理 是將要包含(include)的文件插入原文件中、將宏定義展開、根據條件編譯命令選擇要使用的代碼,最後將這些代碼輸出到一個「.i」文件中等待進一步處理;

轉換 是把C/C++代碼(好比上面的".i"文件)「翻譯」成彙編代碼;

編譯 是將用助記符號表示的彙編語言翻譯成符合必定格式的機器語言;

連接 是將彙編生成的OBJ文件、系統庫的OBJ文件、庫文件連接起來,最終生成能夠在特定平臺運行的可執行程序。

好了,寫着寫着忘記Java程序的正事了。

你們所說的Java,有兩個層面意思,一個是做爲編程語言的Java,另外一個是做爲程序運行環境的Java。這就是Java的特殊所在,特殊就特殊在Java有Java虛擬機。

Java程序也須要編譯,可是沒有編譯成機器語言,而是編譯成字節碼文件,而後在Java虛擬機用解釋的方式執行字節碼。

Java虛擬機

編譯 是將Java源代碼「翻譯」爲Java虛擬機可執行的字節碼文件,保存到硬盤上;

加載 是將生成在內存上的字節碼文件的副本,加載到Java虛擬機上;

Java虛擬機 加載後字節碼後,執行方式有兩種,一種是即時編譯器,另外一種是字節碼解釋器,以下圖:

Java虛擬機執行引擎

即時編譯和解釋執行的區別以下:

解釋執行:將編譯好的字節碼一行一行地翻譯爲機器碼執行。

編譯執行:以方法爲單位,將字節碼一次性翻譯爲機器碼後執行。

軟件 是指Java虛擬機對於系統來講,是一個應用,是用某個高級語言編寫的應用。

固然,Java虛擬機對Java程序來講,是一個運行的環境。咱們能夠對比分析一下,把Java源代碼想象成彙編語言源代碼,字節碼想象成本地CPU可執行的機器語言,Java虛擬機想象成本地CPU

因此這就是爲何說Java是跨平臺的,由於Java虛擬機是一個應用嘛。不過,不一樣的系統,應用也是不一樣的,因此係統不一樣,Java虛擬機也是不一樣的,可是字節碼文件能夠不變的,能夠直接到其它不一樣系統上的虛擬機解析執行的。

Java虛擬機運行的是字節碼,字節碼對Java來講是十六進制;本地CPU執行的是機器碼(機器語言),機器碼對系統來講是二進制。不過,字節碼文件放在本地是0和1組成的,只是不能被本地系統解析執行,須要Java虛擬機即時編譯或解釋執行。

「百聞不如一見」,咱們看看*.class用記事本打開會是怎麼樣的。

記事本

這打開是亂碼的啊?這是由於以class爲後綴名的字節碼文件在Java中保存的是十六進制,那咱們要看十六進制如何看呢?

咱們能夠用Sublime Text 3打開字節碼文件,但打開以前Sublime Text 3須要安裝HexViewer插件,才能夠看十六進制的,具體安裝過程能夠到網上搜索。打開以後,以下圖所示:

Sublime Text 3

能夠看到全部的數字都是十六進制的,接下來下一步就加載到Java虛擬機上去了,具體用即時編譯的仍是解釋執行的,或者在大項目中即時編譯和解釋執行都是能夠共同打配合的,由於Java虛擬機在不一樣的場景下用的是不一樣的優化手段。
喜歡本文的朋友,微信搜索「算法無遺策」公衆號,收看更多精彩的算法動畫文章

相關文章
相關標籤/搜索