其實我是一個標題黨,不小心把大家吸引進來。從這篇文章開始分享一些真正的技術方面的東東了,為了使文章更具有可讀性,內容會穿插一下小故事或八卦,心得等。文章力爭不局限于技術方面的人員閱讀,所謂授之以魚不如授之以漁,文章以輕松的口吻跟大家聊一下技術。
我為什么叫Gregorius
下面開始切題,幾年前當我開始看《linux 內核完全剖析》這本書時,同時也了解到傳奇人物linus的彪悍人生,非常有個性的一個人,愛憎分明,大學時就寫出了linux內核,一直到現在都掌控著內核源代碼的核心,大名鼎鼎的github就是linus不滿現有源代碼版本管理一氣之下寫出來的。此書中有個對時間處理的函數,用途是取當前時間到初始時間的值,unix系的系統時間都是以1970-01-01為起點的,之所以以這個時間為初始時間是因為之前系統都是32的,只能表示68年的時間,作為權衡以此時間作為計算機的紀元時間。
此時間函數linus加了注釋,大致意思是為什么不用閏年呢,閏年又稱為稱為"儒略歷"或"愷撒歷",由古羅馬的愷撒在公元前46年制定的,1582年羅馬教皇格里高利十三世(Gregorius XⅢ)對"儒略歷"又進行修改,所以我的名字就來源此。
java虛擬機的誕生
java虛擬機是java能夠跨平臺運行的基石,自從java誕生以來,虛擬機的發展可謂是百花齊放,就連不可一世的微軟也是java的鐵桿粉絲,也曾開發出自己的java虛擬機,但是sun一紙訴文將微軟告上法庭,結果促成了.net的誕生,可謂一失足成千古恨,不然java現在可以一統江湖。
如果你看完《linux 內核完全剖析》這本書或者對《via clr c#》有所了解,那么再來看java虛擬機相關的東西那就是相當容易了。
編譯原理
首先從計算機的編譯原理開始,對于傳統的計算機編譯過程來說,按部就班分為詞法分析,語法分析,抽象語法樹,解析執行。但是對.net和java來說,不能走尋常路,因為兩者都是跨平臺需要,都有一個中間結構,對于.net來說就是il和clr,對于java來說就是虛擬機指令和虛擬機了,這些指令操作的都是自己的虛擬存儲設備,如果需要轉為物理地址,需要動態解析,java為了兼容大多數虛擬機的優化,把之前靜態編譯階段的優化都放到了動態解析階段來。
體系結構
我們所說的java虛擬機指的是hot spot虛擬機,是sun之前收購過來的。虛擬機的存儲結構主要分為程序計數器,java虛擬機棧,本地方法棧,java堆,方法區,運行時常量,直接內存,堆主要用來存放對象,棧用來存放方法變量這些。java對于c++的優勢主要在于gc,垃圾回收機制,回收的主要內容就是堆上的東西,棧不需要回收,用完自動清空,對c++來說最大的痛苦莫過于指針操作,一不小心就把系統整掛了,所以自從有了垃圾回收機制語言的出現,程序猿們從此過上了快樂的生活。
垃圾回收算法
垃圾回收算法又稱為休克算法,只要垃圾回收機制啟動,就像給虛擬機施了魔法一樣讓,整個世界停止下來。接下來就是媽媽開始打掃衛生了,那媽媽怎么知道你的東西要不要回收呢?方式有很多種,限于篇幅我們直接說主流的方式,就是根引用算法,所有的東西都是媽媽的,媽媽在打掃時首先會記錄一下誰在用,打掃階段問你還用不用,如果都不用了,就把它回收回去,下次想用再找媽媽申請。
CLR Loader Vs Java ClassLoader
雙親委派模式是java類加載模型,類在加載時優先使用父類的加載器進行加載,同一個類只能在同一個類加載器里面加載一次,不同的類可以在不同的類加載器進行加載,但是不同的類加載器加載的類引用是不同的,就是表現為不同的實例。CLR 可以加載類的多個版本,但是只能通過AppDomain進行卸載,擴展性較差。我的結論:Java ClassLoader簡單優雅、功能強大、非常靈活,但對多版本不提供支持;CLR Loader非常簡單、支持多版本、但不太靈活且擴展性稍差。
語法糖
java從1996年以來,基本上是每兩年發布一個版本,由于09年的oracle 收購案導致jdk 1.7遲遲沒有開發出來,然而.net在此前后按部就班推出了較多重要的版本,表現在語法糖之間的差異與java越拉越大。語法糖可以提高程序猿的生產力,也是語言先進性的一個重要標識。
真假泛型
java的泛型只是一個語法糖,java采用類型擦除來初實現的泛型,在運行時將泛型轉為原生類型來進行解析,所以java的泛型又稱為假泛型。.net的泛型實際上是一個真正的類型,是CLR直接支持的,也稱為類型膨脹,所以.net的泛型為真泛型。假泛型也是java經常被詬病的原因。
java虛擬機博大精深,本文只是淺嘗輒止,文中如有不當,敬請批評指出。