如果你尚未閱讀深入java虛擬機,推薦你先閱讀深入理解計算機系統。
如果你已經(jīng)閱讀過(guò)深入理解計算機系統,推薦你閱讀深入java虛擬機。
如果這兩本書(shū)你都閱讀過(guò)或者都在閱讀,我就不知道說(shuō)什么好了。
java虛擬機(jvm)是建立于一個(gè)本地系統之上沙箱之中。
這個(gè)基礎天生便決定了java的平臺平臺無(wú)關(guān)性。
我們所編寫(xiě)的java程序調用java api,由java api調用 本地方法(動(dòng)態(tài)庫)操作本地系統。
由此帶來(lái)了內存管理,安全管理等一系列問(wèn)題。

java api沒(méi)有通過(guò)提供強制裝換指針或者通過(guò)指針運算直接訪(fǎng)問(wèn)內存的方法。
java使用自動(dòng)垃圾回收機制,通過(guò)停止對一個(gè)java對象的引用來(lái)促使垃圾收集器自動(dòng)回收這個(gè)對象所占據的內存。
java使用數組邊界檢查而防止出現因此而引發(fā)的內存沖突。
java的平臺無(wú)關(guān)性
java虛擬機規范規定了java虛擬機中基礎類(lèi)型的規格,因此通過(guò)使用不同平臺的java虛擬機,而跨越不同的系統平臺實(shí)現。
因此編寫(xiě)java程序一個(gè)很重要的原則就是不要直接或者間接調用不屬于java api的本地方法。
對java虛擬機的依賴(lài)
編寫(xiě)平臺獨立的java程序時(shí)候,要遵循兩條原則:
1 不要依賴(lài)及時(shí)終結來(lái)達到程序的正確性 。
不同的java虛擬機有不同的垃圾回收機制的實(shí)現。
2 不要依賴(lài)線(xiàn)程的優(yōu)先級來(lái)達到程序的正確性。
不同的java虛擬機有不同的線(xiàn)程優(yōu)先級的實(shí)現。為了保障多線(xiàn)程java程序的平臺無(wú)關(guān)性,必須依賴(lài)同步機制而不是優(yōu)先級機制來(lái)協(xié)調線(xiàn)程。
java沙箱機制是java程序運行在一個(gè)受限的內存空間。
例如某個(gè)java程序產(chǎn)生了outofmemory的異常,只會(huì )導致這個(gè)java程序終止。并不會(huì )導致其他java程序或者其他應用程序終止。
java沙箱由以下幾部分組成:
類(lèi)裝載器體系結構在三個(gè)方面對java沙箱起作用:
1.防止惡意代碼去干涉善意代碼。
2.守護了被信任的類(lèi)庫的邊界
3.將代碼歸入了保護域,該保護域確定了代碼可以進(jìn)行哪些操作。
類(lèi)裝載器通過(guò)為不同的類(lèi)提供不同的類(lèi)裝載命名空間來(lái)防止惡意代碼干涉善意代碼。相同命名空間內的類(lèi)可以相互訪(fǎng)問(wèn)而不同命名空間內的類(lèi)彼此并不可視因而也無(wú)法相互訪(fǎng)問(wèn)。
類(lèi)裝載器守護被信任的類(lèi)庫邊界通過(guò)使用不同的類(lèi)裝載器裝載不同的包而實(shí)現的。
class文件校驗器用來(lái)檢驗class文件的字節碼。防止阻止方法內的跳轉指令跳到方法之外。
class文件會(huì )對一個(gè)class文件的字節碼序列進(jìn)行四次掃描
1 class文件的結構檢查
java的class文件是以0xCAFEBABE開(kāi)頭作為文件類(lèi)型標識的。主要檢查class文件的完整性,保障這個(gè)字節序列遵從class文件的文件格式,這樣才能編譯成在方法區的內部數據結構。第2,3,4次掃描是在方法區內進(jìn)行的。
2 類(lèi)型數據的語(yǔ)言檢查
檢驗器檢查每個(gè)組成部分,確認其是否是所屬類(lèi)型的實(shí)例,它們的結構是否正確。其目的是為了確認每個(gè)方法描述符都是符合特定格式,格式正確的字符串。還會(huì )檢查這個(gè)類(lèi)本身是否符合特定的條件??傊?,檢驗器會(huì )檢驗有編譯器產(chǎn)生的class文件是否遵守一些java語(yǔ)言在編譯時(shí)必須遵守的強制規則。
3字節碼驗證
字節碼流代表了java的方法,它是由被稱(chēng)為操作碼的單字節指令組成的序列。每個(gè)操作碼后面都跟著(zhù)一個(gè)或者多個(gè)操作數(這一點(diǎn)很類(lèi)似匯編語(yǔ)言的指令)。操作數用于在java虛擬機執行操作碼指令時(shí)提供所需的額外的數據。執行字節碼時(shí),依序執行每個(gè)操作碼,這樣就在java虛擬機內部形成了執行的線(xiàn)程。每個(gè)線(xiàn)程被授予自己的java棧。這個(gè)棧就是由不同的棧幀組成的。每一個(gè)方法的調用將獲得一個(gè)自己的棧幀(其實(shí)就是一個(gè)內存片段),其中存儲著(zhù)局部變量和計算的中間結果。在棧幀中用于存儲方法的中間結果的部分被稱(chēng)為該方法的操作數棧。操作碼和它的(可選)操作數可能指存儲在操作數棧中的數據或者存儲在方法棧幀中的局部變量中的數據。這樣,在執行一個(gè)操作碼時(shí),除了可以使用緊隨其后的操作數,虛擬機還可以使用操作數棧中的數據,或存儲在方法棧幀中的局部變量中的數據,或兩者都使用。
字節碼驗證要校驗直接碼流符合java的操作碼和操作數能夠被java虛擬機安全地執行。
4符號引用的驗證
java虛擬機將追蹤直接碼流中的符號引用,并且確保符號應用的資源可用。如果該資源不可用并不立即拋出noclassdeffounderror錯誤,而是在運行時(shí),這個(gè)類(lèi)被首次引用時(shí)才拋出。
動(dòng)態(tài)連接是將一個(gè)符號引用解析為直接引用的過(guò)程。當java虛擬機執行字節碼時(shí),如果遇到一個(gè)操作碼,這個(gè)操作碼第一次使用一個(gè)指向另一個(gè)類(lèi)的引用,那么java虛擬機就要解析這個(gè)引用。
1)查找被引用的類(lèi),如果必要的話(huà)就裝載它。
2)將符號引用替換為直接引用,例如一個(gè)指向一個(gè)類(lèi),方法或者字段的指針或者偏移量。

聯(lián)系客服