
計(jì)算機(jī)只能識(shí)別機(jī)器碼0101...編程語(yǔ)言->能執(zhí)行的機(jī)器碼 需要經(jīng)過 預(yù)處理->編譯->匯編->鏈接->機(jī)器碼過程。一個(gè)語(yǔ)言處理系統(tǒng)的示意圖如下:

編譯器 是將源語(yǔ)言程序一次性翻譯成一個(gè)等價(jià)的,用目標(biāo)語(yǔ)言編寫的程序。還存在另一種常見的語(yǔ)言處理器,解釋器:它是逐個(gè)語(yǔ)句的執(zhí)行源語(yǔ)言程序。由一個(gè)編譯器產(chǎn)生的目標(biāo)語(yǔ)言程序通常比一個(gè)解釋器快,但解釋器的錯(cuò)誤診斷效果通常更好。
Java語(yǔ)言處理器結(jié)合了編譯和解釋的過程。一個(gè).Java源程序首先被編譯為.class字節(jié)碼文件,被加載到虛擬機(jī)中,然后由虛擬機(jī)將字節(jié)碼翻譯成機(jī)器碼。

虛擬機(jī)的好處在于:一旦一個(gè)程序被轉(zhuǎn)換成 Java 字節(jié)碼,那么它便可以在不同平臺(tái)上的虛擬機(jī)實(shí)現(xiàn)里運(yùn)行。實(shí)現(xiàn)一次編寫,到處運(yùn)行。另外一個(gè)好處是它帶來(lái)了一個(gè)托管環(huán)境。這個(gè)托管環(huán)境能夠代替我們處理一些代碼中冗長(zhǎng)而且容易出錯(cuò)的部分,如自動(dòng)內(nèi)存管理與垃圾回收。
在Hotspot中,虛擬機(jī)翻譯字節(jié)碼有兩種方式:
1.解釋執(zhí)行
即逐條將字節(jié)碼翻譯成機(jī)器碼并執(zhí)行。
2.即時(shí)編譯
即將一個(gè)方法中包含的所有字節(jié)碼編譯成機(jī)器碼后再執(zhí)行。
前者的優(yōu)勢(shì)在于無(wú)需等待編譯,而后者的優(yōu)勢(shì)在于實(shí)際運(yùn)行速度更快。HotSpot 默認(rèn)采用混合模式,綜合了解釋執(zhí)行和即時(shí)編譯兩者的優(yōu)點(diǎn)。它會(huì)先解釋執(zhí)行字節(jié)碼,而后將其中反復(fù)執(zhí)行的熱點(diǎn)代碼,以方法為單位進(jìn)行即時(shí)編譯。
即時(shí)編譯建立在程序符合二八定律的假設(shè)上,也就是百分之二十的代碼占據(jù)了百分之八十的計(jì)算資源。
好了,裝X結(jié)束。

阿姨知道的編譯知識(shí)全在上面了。。(っ╥╯﹏╰╥c)
如題,下面我們來(lái)看一下讓Java項(xiàng)目運(yùn)行起來(lái)我們能做什么。
我們能做的很簡(jiǎn)單,當(dāng)然不是寫虛擬機(jī)。我們只需要:
1.執(zhí)行command javac,將.Java文件變?yōu)?class文件。
2.執(zhí)行command java,讓.class文件運(yùn)行起來(lái)。
也就是 執(zhí)行command :)
Java程序的運(yùn)行方式
Java程序可以通過java命令運(yùn)行.class文件或運(yùn)行可執(zhí)行Jar文件。
我們先看第一種方式:從Hello World開始。
運(yùn)行.class文件
Step1:編寫Java文件

Step2:執(zhí)行 command javac
將.Java文件變?yōu)?class文件

小貼士:class文件的全路徑名是包名目錄+ 類文件名。
Step3:執(zhí)行 command java
運(yùn)行.class文件

神奇,我們沒有用IDE讓Java程序運(yùn)行起來(lái)了 :)
小伙伴先別噴老阿姨,哪特么有這么簡(jiǎn)單的Java項(xiàng)目啊。。我們工作中用的明明都是Jar文件啊...
Jar文件咋運(yùn)行啊??!

運(yùn)行可執(zhí)行Jar文件
Jar文件是基于ZIP文件格式的一種文件格式,它將大量的Java類文件、相關(guān)的元數(shù)據(jù)和資源(文本、圖片等)文件聚合到一個(gè)Jar文件中,此外還包含一個(gè)可選的META-INF文件夾。這個(gè)文件夾下的文件或文件夾主要用來(lái)打包和擴(kuò)展配置信息,包括安全,版本,擴(kuò)展程序和服務(wù)等。如MANIFEST.MF文件定義了擴(kuò)展和打包的相關(guān)數(shù)據(jù)信息。
一個(gè)Jar文件通常在項(xiàng)目中用作第三方類庫(kù)使用,也是項(xiàng)目構(gòu)建的一部分。
生成一個(gè)Jar文件大致分為兩步:
1.將源文件編譯為.class文件
2.通過 command jar命令將.class文件,資源文件等等打成一個(gè)文件格式的Jar文件。
我們以一個(gè)SbDemo項(xiàng)目為例來(lái)看Jar文件的打包和運(yùn)行。項(xiàng)目目錄結(jié)構(gòu)如下:

Test2.java中調(diào)用了Test1.java的方法,

我們需要先將Test1.java編譯并打成一個(gè)Test1.jar文件,然后通過Test1.jar將Test2.java編譯并打成一個(gè)可執(zhí)行的Test2.jar文件。
可執(zhí)行和不可執(zhí)行的Jar文件 區(qū)別在于是否在Jar文件中指定了main方法的入口,我們后面再看。
Step1:Test1.java的編譯

Step2:將編譯后的classes/com/Test1.class文件打成一個(gè)Test1.jar包
Java中和jar包相關(guān)的命令是jar命令,生成一個(gè)jar包我們需要定義信息文件(manifest-file),它可以定義所生成jar包的classpath類搜索路徑,jar包的入口類等等??梢岳斫鉃?strong>與Jar包相關(guān)的元數(shù)據(jù)配置信息。
Step2.1 書寫信息文件
這里我們使用resources/manifest-test1.text文件作為信息文件

是的,Test1.java太簡(jiǎn)單了,就是打成一個(gè)可被他人引用的jar包,信息文件不重要。
Step2.2 執(zhí)行打包命令
Step3. 編譯Test2.java文件
因?yàn)門est2.java中引用了com.Test1類,所以我們需要在編譯時(shí)指定Classpath路徑。
Classpath:顧名思義,是指待編譯類依賴的類所在路徑位置。我們可以通過 javac 的 -cp 參數(shù)指定。
關(guān)于編譯時(shí)classpath的值優(yōu)先級(jí)如下:
- 如果沒有傳入classpath參數(shù),將使用環(huán)境變量CLASSPATH的值。(小伙伴不知道環(huán)境變量咋查看和設(shè)置?去看阿姨的上一篇文章:)
- 如果沒有發(fā)現(xiàn)環(huán)境變量CLASSPATH,將使用 執(zhí)行命令的當(dāng)前文件夾(.)。
- 如果javac命令行 通過
-classpath or -cp參數(shù)指定了類路徑值,則優(yōu)先級(jí)最高。
這里我們使用-cp指定Test1.jar所在位置

可以看到classes目錄下已經(jīng)生成了com2/Test2.class文件了。
Step4. 將編譯后的Test2.class和它依賴的Test1.jar一起打成一個(gè)可執(zhí)行的Jar包
Step4.1 書寫信息文件
這時(shí)候我們使用信息文件resources/manifest-test2.text文件指定這些信息

Step4.2 執(zhí)行Jar包生成命令

可以看到在lib目錄下生成了Test2.jar
Step5.運(yùn)行我們的可執(zhí)行Jar

大功告成了,我們的SbDemo項(xiàng)目Run起來(lái)了...
當(dāng)然實(shí)際項(xiàng)目不可能人肉編譯,打包。我們需要通過Maven/Gradle等構(gòu)建工具,幫助我們管理代碼之間的Jar包依賴,構(gòu)建,部署...我們可能大多時(shí)候通過點(diǎn)一下IDE就托管了Maven的構(gòu)建部署命令。
拿Maven舉例子,Maven首先定義了一套項(xiàng)目結(jié)構(gòu),我們按照它的結(jié)構(gòu)書寫代碼,引入各個(gè)模塊所需要的Jar包依賴。然后Maven可以通過自己的生命周期管理項(xiàng)目的清理,構(gòu)建,打包,部署階段。每個(gè)階段有對(duì)應(yīng)的Maven插件執(zhí)行相應(yīng)的目標(biāo)。IDE又整合了Maven,使我們通過點(diǎn)吧點(diǎn)吧按鈕就完成了項(xiàng)目的運(yùn)行。
但是當(dāng)一個(gè)項(xiàng)目并沒有按照規(guī)范的構(gòu)建工具結(jié)構(gòu)搭建,或者項(xiàng)目沒有成功運(yùn)行報(bào)錯(cuò)時(shí),了解Java實(shí)際的編譯運(yùn)行過程會(huì)對(duì)理解、解決這類問題有所幫助。
參考資料:
[1].《編譯原理》序 (?′ω`?)?
[2].https://time.geekbang.org/column/article/11289