手寫JVM系列(1)-準備工作

本系列文章主要根據(jù)張秀宏老師的—— 《自己動手寫 java 虛擬機》一書所做的筆記末盔。該書實現(xiàn)了大部分 JVM 的功能功偿,包括class文件解析盆佣、類加載、指令集械荷、解釋器共耍、方法調(diào)用、數(shù)組和字符串的處理吨瞎、異常處理等痹兜。這本書可以說是了解 Java 虛擬機最淺顯易懂的書籍,隨書提供了每個章節(jié)的代碼关拒,可以完美運行佃蚜。但是這本書所附帶的代碼是用 go 語言書寫的庸娱,如果想要看懂這本書的代碼着绊,首先要學會 go 語言的基本語法。這邊博客記錄了在閱讀這本書之前的準備工作熟尉。我在練習中是根據(jù)張老師的代碼用 Java 語言又實現(xiàn)了一遍归露。雖然用 Java 語言在實現(xiàn)一個自己的虛擬機,然后跑在自帶的虛擬機上有點滑稽斤儿,但是重點還是了解虛擬機內(nèi)部的基本原理剧包。

貼出張秀宏老師這本書的代碼

如果你想跟著張秀宏老師的代碼學習 JVM,那么下面的內(nèi)容正是為你準備的往果。而如果你不想花時間學習另一門語言疆液,那么可以參考我用 Java 實現(xiàn)的相同功能的代碼,下面關(guān)于 go 的準備工作陕贮,可以忽略堕油。

安裝 Go 開發(fā)環(huán)境

下載

Go 語言中文網(wǎng),這個下載速度快一點,下載最新版本之后一路next即可。

安裝后肮之,其實安裝腳本已經(jīng)自動幫我們把 Go 的安裝路徑添加到系統(tǒng)的環(huán)境變量中了掉缺, 查看系統(tǒng)環(huán)境變量,發(fā)現(xiàn)多了一個 GOROOT,其值為:C:\go(默認的安裝路徑)并且在path中,也自動把 GOROOT\bin添加了進來,因此直接打開命令行窗口,輸入go version命令,就會輸出安裝的go的版本信息.

配置環(huán)境

既然上一步安裝Go時已經(jīng)添加了環(huán)境變量了,那么接下來還要配置什么呢?

Go希望我們把所有的代碼都存在在同一個目錄下,這就好比我們用eclipse時需要一個workspace,但是eclipse中的workspace可以有多個,而Go希望在一臺主機上只有一個workspace,所以我們在這里要指定一個,例如D:\workspace,這個位置隨意,文件夾名字隨意,然后和Go進行關(guān)聯(lián),這里的關(guān)聯(lián)方法就是在環(huán)境變量中,添加一個GOPATH,其值為剛剛設(shè)定的D:\workspace戈擒,其指明了除GOROOT之外的包含 Go 項目源代碼和二進制文件的目錄眶明。這和Java中的 classpath 有些類似。當然你可以為GOPATH指定多個路徑作為 workspace 的筐高,但是這里還是建議一個就好搜囱。

接下來,在D:\workspace中添加一個目錄src,這一步是必須的,所有的Go源代碼都必須放在這個src目錄下,那有人問,如果我有多個項目,所有源代碼都放在這個目錄下,怎么分清哪個源代碼歸屬于哪個項目呢? 方法很簡單,就是在src目錄下再用不同的文件夾作為分隔,一個項目一個文件夾,自然就分開了;

Go 語言的包結(jié)構(gòu)

Go語言以包為單位組織源代碼丑瞧,包可以嵌套,形成層次關(guān)系蜀肘。書中編寫的Go源文件全部放在jvmgo包中嗦篱,其中每一章的源文件又分別放在自己的子包中。包層次目錄結(jié)構(gòu)有一個簡單的對應關(guān)系幌缝,比如灸促,第 1 章的代碼在jvmgo\ch01目錄下。除第 1 章以外涵卵,每一章都是先復制前一章代碼浴栽,然后進行修改和完善。每一章的代碼都是獨立的轿偎,可以單獨編譯為一個可執(zhí)行文件典鸡。

所形成的目錄結(jié)構(gòu)是:

- D:\workspace
    - src
        - jvmgo
            - ch01
            - ch02
            ...

之前也說過在 src 下,通過文件夾將不同的項目分割開坏晦。這里的例子是使用了個二級文件夾來區(qū)分的萝玷,每個項目都是放在src/jvmgo/chXXX下的,我們平時用一級目錄當然也是可以的昆婿。那么其目錄看起來應該是這樣的:

- D:\workspace
    - src
        - ch01
        - ch02
        ...

在每一個章節(jié)的 chX(go 的工程)中,都必須有一個main的包,這個包中的某個文件必須要包含一個main方法,因為這里每個文件夾被看做一個獨立的工程球碉。這個也很好理解,因為Java工程中,每個Java都可以有一個public static void main(String[] args)方法,這一點不足為奇,但是要注意的是,一旦你選定某個文件夾為一個項目(eg:jvmgo/ch05),并且使用go install jvmgo\ch05

來生成一個 exe 文件, 那么這個目錄下只能有一個main方法,不能有多個,否則就報錯,類似于

D:\workspace\src\jvmgo\ch05\main2.go:3: main redeclared in this block
        previous declaration at E:\workspace\src\jvmgo\ch05\main.go:8

這是因為我在main.go中聲明了一個main方法,又在main2.go中聲明了一個main方法,所以就報了重復定義的錯誤。

還有一點要說明的是:可以直接在命令行輸入go install your/dir/name系統(tǒng)會自動從GOROOT/srcGOPATH/src兩個文件中找your/dir/name,而不用非進入到GOPATH/src路徑下執(zhí)行,而且如果your/dir/name在上述兩個路徑中均存在,那么前者優(yōu)先級更高仓蛆。

前面是使用go install命令生成可執(zhí)行文件,但是如果你使用 go run xxx.go,那么不用保證 xxx.go 所在的包中main方法是唯一的,main包中其它文件也可以包含main方法,因為你運行的是單個文件,不過這只是自己平時練習時用,真正的項目都不會只有單個文件那么簡單睁冬。

關(guān)于 Go 語言的包結(jié)構(gòu),下面兩篇文章是不錯的參考看疙。

GO 項目的目錄結(jié)構(gòu)

GOROOT豆拨、GOPATH 和 project 目錄說明

快速入門 Go 語言

因為本項目是想用Java實現(xiàn)書中的JVM項目,而書中所提供的是Go的源碼,所以這里只要求能看懂Go的代碼就可以,不必深入細節(jié),相信看到這篇文章,想學習JVM,那么你的Java語言一定已經(jīng)很熟練了,那么再快速學習一門語言是很快的,這里推薦Go 的官方教程,一天就能看完,一定要有耐心。

上面提供的網(wǎng)站很不穩(wěn)定,如果人品好的話,打開之后,趕緊一口氣學完;運氣差點肯定就打不開,沒關(guān)系,這里有離線的版本,效果是一樣的;

如果你已經(jīng)安裝好了Go的開發(fā)環(huán)境,那么直接打開命令行,輸入go tool tour,瀏覽器就會自動打開一個頁面,和在線版是一樣,而且速度很快,你可以在右側(cè)的代碼區(qū)編寫自己的代碼并運行,這里代碼的改動都是保存在本地的能庆。

go 常用命令

  • go build:編譯出可執(zhí)行文件施禾,默認位置是和 main 方法所在的文件同目錄下。
  • go run
  • go install:先執(zhí)行go build命令搁胆,然后把最終編譯成的可執(zhí)行文件放到 GOPATH/bin 目錄下弥搞。
  • go get:從指定源上面下載或者更新指定的代碼和依賴(git clone),并對他們進行編譯和安裝(go install)丰涉。

依然用上面的例子來說明拓巧,例如我們下得到第 1 章(每一章都是一個單獨的項目,相互之前沒有關(guān)系)的一個可執(zhí)行程序一死。

go build

構(gòu)建編譯由導入路徑命名的包肛度,以及它們的依賴關(guān)系,但它不會安裝結(jié)果

使用方法:

go build [-o 輸出名] [-i] [編譯標記] [包名]

其具體參數(shù)可以參考下面給出的參考鏈接投慈,這里簡單提一下 go build 的使用:

  1. 當編譯單個 main 包(文件)承耿,則生成可執(zhí)行文件冠骄。
  2. 當編譯單個或多個包非主包時(不包含 main 方法),只構(gòu)建編譯包加袋,但丟棄生成的對象(.a)凛辣,僅用作檢查包可以構(gòu)建
  3. 當編譯包時职烧,會自動忽略'_test.go'的測試文件扁誓。

在命令行進入到GOPATH/src/jvmgo/ch01路徑,執(zhí)行:go build main.go蚀之,這樣就會產(chǎn)生一個 main.exe 的可執(zhí)行文件(默認情況下這個文件的名字為源文件名字去掉.go 后綴)蝗敢,其與 main.go 在同一目錄下。但是如果你真的這樣做是無法生成 main.exe 可執(zhí)行文件的足删,因為 build 命令構(gòu)建單個文件時寿谴,雖然滿足上面的條件 1,但是該文件中還使用了其它的文件中的方法失受。我們平時自己寫一個簡單的打印 helloword 的程序讶泰,所有代碼都在一個文件中,用該命令是可以得到一個可執(zhí)行文件的拂到,但是如果我們的文件中依賴了其它文件中的方法痪署,那么這時候就會報錯,找不到 xxx 方法谆焊。所以這個命令平時使用的不是很多惠桃,用的最多的還是 install 命令浦夷。

參考:go build

go run

和 go build 類似辖试,用來運行單個包含 main 方法的文件,其不生成 exe 文件劈狐,而是直接在命令行中運行該 main 文件罐孝。該命令常用來測試一些功能。

go install

在命令行任意路徑下執(zhí)行:go install jvmgo/ch01肥缔,這樣就會在GOPATH/bin路徑下產(chǎn)生一個 ch01.exe(install 命令以 main 方法所在的上一級目錄名作為可執(zhí)行程序名)的可執(zhí)行文件莲兢。之前我們也提到了,必須在 GOPATH 路徑下手動創(chuàng)建一個 src 的文件夾续膳,并將我們寫的所有的 go 文件都剛在該路徑下改艇,但執(zhí)行了上面的 install 命令后,發(fā)現(xiàn)在 GOPATH 下除了 src坟岔,多出了兩個文件夾谒兄。下面解釋下這三個文件夾的作用。

  • src 包含項目的源代碼文件社付;
  • pkg 包含編譯后生成的包/庫文件承疲;
  • bin 包含編譯后生成的可執(zhí)行文件邻耕。

這里特別要提一下的是 pkg 文件夾,其所放的內(nèi)容是聲明燕鸽?我們知道大型項目中都不可能將所有代碼都寫在一個文件中的兄世,而是要分包。那么各個包在 go install 時啊研,會被編譯成 xxx.a御滩,類似 C 中的鏈接庫。

但是 go install 也是有坑的党远,詳見:go install 的工作方式

go 中的文件夾名和包名

在 Java 中艾恼,類的包名和文件路徑必須是對應的,而在 go 中則沒有這種硬性規(guī)定麸锉,但是為了規(guī)范代碼钠绍,Google 官方還是強烈建議我們寫 go 代碼時,文件夾名和包名保持一致花沉。如果不一致柳爽,例如我們有一個文件夾,名為 A碱屁,其下有個 go 文件磷脯,自定義的包名是 B(每個子目錄中只能存在一個 package,否則編譯時會報錯)娩脾,那么在其它文件中使用該文件中的方法時赵誓,需要import A,而在代碼中使用其方法時柿赊,則使用B.func()俩功。所以這還是強烈建議,包名和所在文件夾名保持一致碰声。

這里有一個特殊的包诡蜓,叫做main,在執(zhí)行 go install 命令時胰挑,如何找到整個程序的入口呢蔓罚?光有 main 方法是不行的,包含 main 方法的 go 文件瞻颂,其包名必須也是main豺谈,同時所有包名為main的 go 文件中,只能有一個 main 方法贡这。只有滿足以上所有要求茬末,才會得到可執(zhí)行文件,如果 main 方法不在main下藕坯,執(zhí)行 go install 团南,go 會將所有包都視為 library噪沙,在 pkg 下生成對應的 xxx.a 文件,而不會有可執(zhí)行文件吐根。

關(guān)于開發(fā)工具

這里推薦使用 Intellij idea + 插件的方式,這里主要是為了看代碼方便,可以很方便的實現(xiàn)方法之間的跳轉(zhuǎn),

go 插件安裝

打開ideasetting->plugin,搜索go,點擊下方的Browse repositorise,找到Go language(golang.org)support plugin,官網(wǎng)地址,安裝后重啟編譯器插件才可以用正歼。

其實用 idea+插件的方式,查看 go 的代碼已經(jīng)很舒服了拷橘,不用額外再配置其他 ide局义,畢竟我們的主要精力還是能看懂 go 的代碼,并不寫任何 go 代碼冗疮。

注意:安裝 go 插件萄唇,需要 idea 的版本為2016.2,我在開發(fā)中使用的 idea 為 COMMUNITY 2016.2.5术幔,最新版本的 idea 無法安裝 go 插件另萤!

bytecode 插件安裝

既然虛擬機是和 class 文件打交道的,就免不了查看字節(jié)碼的內(nèi)容诅挑,這里提供一個好用的查看字節(jié)碼的插件——jclasslib Bytecode viewer四敞,安裝方式同 go 插件的安裝。

使用方法:首先要單獨編譯當前窗口的 java 文件拔妥,使其生成 class 文件忿危,然后在編譯器的View中選擇show Bytecode with jclasslib

用 idea 看源碼

為了配合idea閱讀《自己動手寫 java 虛擬機》的源碼,這里最簡單的做法:

  1. 新建一個 go 項目,命名為jvmgo,路徑為GOPATH/src
  2. 需要看哪一章的源碼,就把作者對應的 jvmgo/文件夾下的ch01(以第一章為例),復制到上一步新建的項目路徑下,最終結(jié)果應該是:GOPATH/src/jvmgo/ch01
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末没龙,一起剝皮案震驚了整個濱河市铺厨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌硬纤,老刑警劉巖解滓,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異咬摇,居然都是意外死亡伐蒂,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門肛鹏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人恩沛,你說我怎么就攤上這事在扰。” “怎么了雷客?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵芒珠,是天一觀的道長。 經(jīng)常有香客問我搅裙,道長皱卓,這世上最難降的妖魔是什么裹芝? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮娜汁,結(jié)果婚禮上嫂易,老公的妹妹穿的比我還像新娘。我一直安慰自己掐禁,他們只是感情好怜械,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著傅事,像睡著了一般缕允。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蹭越,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天障本,我揣著相機與錄音,去河邊找鬼响鹃。 笑死彼绷,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的茴迁。 我是一名探鬼主播寄悯,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼堕义!你這毒婦竟也來了猜旬?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤倦卖,失蹤者是張志新(化名)和其女友劉穎洒擦,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體怕膛,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡熟嫩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了褐捻。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掸茅。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖柠逞,靈堂內(nèi)的尸體忽然破棺而出昧狮,到底是詐尸還是另有隱情,我是刑警寧澤板壮,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布逗鸣,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏撒璧。R本人自食惡果不足惜透葛,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望卿樱。 院中可真熱鬧僚害,春花似錦、人聲如沸殿如。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽涉馁。三九已至门岔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間烤送,已是汗流浹背寒随。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留帮坚,地道東北人妻往。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像试和,于是被迫代替她去往敵國和親讯泣。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容

  • 1. 分布式系統(tǒng)核心問題 參考書籍:《區(qū)塊鏈原理阅悍、設(shè)計與應用》 一致性問題例子:兩個不同的電影院買同一種電影票好渠,如...
    molscar閱讀 905評論 0 0
  • windows下 golang 安裝與配置請參照:http://www.reibang.com/p/b6f34ae...
    molscar閱讀 2,113評論 0 7
  • 一、簡介 Go(又稱Golang)是Google開發(fā)的一種靜態(tài)強類型节视、編譯型拳锚、并發(fā)型,并具有垃圾回收功能的編程語言...
    Mr_Michael閱讀 488評論 0 0
  • 1.2 GOPATH與工作空間 前面我們在安裝Go的時候看到需要設(shè)置GOPATH變量寻行,Go從1.1版本到1.7必須...
    xiao_kong閱讀 199評論 0 0
  • 前言:我覺得java程序員學golang很容易上手萨惑。關(guān)于GOROOT、GOPATH贞滨、GOBIN這些環(huán)境變量的設(shè)置,...
    haokeed閱讀 11,227評論 2 7