程序员想知道代码是怎样跑起来的
某一天,程序員使用Java語言實現累加求和的方法,將文件命名為Sample.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;} }程序員不想直接點擊運行,使用javap編譯了Sample.java文件,可以看到Sample.java所在的目錄下,生成了Sample.class文件。
那要是匯編語言,具體步驟應該是怎樣的啊?
不過,什么是匯編語言?匯編語言其實和硬件息息相關,也就是脫離不了實際的硬件環境,無法跨平臺運行,因為匯編語言是人們用助記符表述CPU的動作。CPU結構不一樣,匯編語言調用的可能也不一樣。
那助記符是什么意思呢?匯編語言的每一行,表示對CPU的一個指令,其語法結構是操作碼 + 操作數。當然也存在只有操作碼,例如ret,表示將處理返回到函數的調用源。
操作碼是對CPU的指令,是動詞,那操作碼是數據,是存儲在CPU的寄存器,是賓語。如mov a b; 表示將b的值賦值給a;add a b; 表示a同b的值相加,并將結果賦值給a。
那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之道公眾號
好文章,我在看??
總結
以上是生活随笔為你收集整理的程序员想知道代码是怎样跑起来的的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为什么k8s中docker容器的启动命令
- 下一篇: YAML字段详解