做者:請叫我紅領巾,轉載請註明出處http://www.cnblogs.com/xxzhuang/p/7453746.html,簡書地址:http://www.jianshu.com/p/b963b3c0ad53html
首先,本篇文章並無涉及原理,而是在筆者擼了《深刻理解Java虛擬機》好幾遍的基礎上講解本身的經驗,從一個新手到如今明白JVM是個什麼玩意,怎麼去理解和明白,講解這樣一個經驗而已。這篇文章並對JVM並無挖掘得很深,在下目前暫時也沒有這個能力,只是以通熟易懂的方式,讓讀者理解JVM是個什麼玩意。下面開始個人講解。java
理解Java的跨平臺特性,是對JVM最直觀的認識。所謂的「一次編譯,處處運行」,爲何C/C++ 卻不能實現呢?這一類語言直接使用物理硬件(或者說操做系統的內存模型),那麼不一樣系統之間的內存模型是不一樣的,好比說Linux和Window,這就意味,在Window編譯好的代碼,卻不能在Linux上運行。《深刻理解Java虛擬機》記錄說,Java虛擬機規範中試圖定義一種Java內存模型(JMM)來屏蔽掉各類硬件和操做系統的內存訪問差別,以實現讓Java程序在各類平臺上都能達到一致性的併發效果。舉個現實的例子,一個只會據說中文的人,要如何和一個只會據說英文的人交流,在Java的世界裏,採用的方式便是給兩邊的人各配一名翻譯官(JVM),因此,這就是爲何JVM要有window版本,也要有Linux版本。算法
衆所周知,Java的程序編譯的最終樣子是.class文件,不一樣虛擬機的對每個.class文件的翻譯結果都是一致的。而對於C/C++而言,編譯生成的是純二進制的機器指令,是直接面對計算機系統的內存,可是,java程序的編譯結果是面向JVM,是要交付給JVM,讓他再作進一步處理從而讓計算機識別運行,這就是所謂的「屏蔽掉各類硬件和操做系統的內存訪問差別」。這裏的特色又和麪向對象推崇的面向接口有着不可描述的關係,我只須要有這麼個規範,不須要去知道接觸你的底層原理實現。編程
JVM,全稱Java Virtual Machine,英文爲Java虛擬機,簡單的探討一下虛擬機這三個字,對後面的學習也是挺舒服的。百度百科描述說,「虛擬機(Virtual Machine)指經過軟件模擬的具備完整硬件系統功能的、運行在一個徹底隔離環境中的完整計算機系統」,可是虛擬機本質仍是該計算機系統的一個進程,能夠類比香港澳門具備高度自治,但本質上他們仍是屬於中國的。爲了方便描述,咱們把整個計算機當成一幢大樓,而虛擬機則是某一個樓層。大樓劃分了一個區域給一個樓層,讓這個樓層本身管理本身,也就對應着,計算機劃分了一個內存給JVM,讓JVM本身管理本身。下面這張圖是筆者的阿里雲服務器上的內存使用狀況,能夠看到JVM足足佔用了接近500M的內存。那麼問題來了,JVM要這麼多的內存幹什麼,這裏面又是怎麼劃分?服務器
在現階段不管什麼編程語言,都是由人類設計發明的,編程語言對於人類來說,是方便本身實現目的的工具之一,因此,編程語言看似是全新的東西,可是這裏面到處均可以看見人類思想的影子,均可以從現實中找到類似的例子。併發
接着上面的例子,JVM是做爲某一個樓層,單獨佔有了一大塊區域(內存)。這個樓層中,有主廳,客廳,客房,這四個之間的區別之一就行,主廳和客廳是公有的,而主房和客房是私有的,這裏對應到JVM層次上便是,有某幾塊內存,是不管是誰訪問,有多少人(線程)訪問,這些共有區域均可覺得他們服務,而客房,私有區域,假定咱們這個樓層比較牛逼,來了多少個客人,就會單獨爲他們建造每一件客房,每一個客人都有本身私有區域,A客人是進不了B客人的房間。編程語言
對應的JVM的層次,便是JVM運行時數據區域劃分爲兩大塊,線程隔離的區域和線程共享的區域。咱們能夠簡單的理解爲,每一個客人便是一條線程。具體對應的區域又是如何劃分的,又有什麼做用,這裏只能從概念上理解和記憶了,傳送門在此輕鬆認識JVM運行時數據區域工具
回想起小時候,不少小夥伴都會一塊兒結伴過來我家玩耍,雖然你們玩得很開心,等到了時間點以後,他們就拍拍屁股走人,留下我家裏一片狼藉,這個時候若是我不收拾一下垃圾的話,我老媽估計就要來拍拍個人屁股了。客人(線程)一樣如此,我來過你的世界,總會留下屬於個人痕跡,是否是垃圾,就要看你本身如何斷定了。這裏就引出另外一個問題,我怎麼判斷是哪一個纔是垃圾,哪一個不是垃圾,只不過是玩耍的時候,我或者小夥伴隨手把老媽的戒指扔到地上而已。站在人類的視角上看,一眼就知道哪一個是垃圾,哪一個不是垃圾,可是計算機可不是這樣,計算機有些時候確實不如人類,明明人類一眼或者幾秒能完成的事情,要讓計算機一樣可以完成對應的功能的話,須要付出千萬倍的代價纔可以實現。學習
筆者的老媽在家裏收拾垃圾的時候,爲了確保扔掉的東西是垃圾,她會將這個東西,一個一個問家裏的每一個人,這個東西是否是你的,你還要不要,當沒有一我的認可說這個東西是屬於他的時候,老媽就將這個東西視爲垃圾,當有人說這個不是垃圾,是他的寶貝的時候,我老媽就這個東西標記一下。JVM採用的是相似的作法,每一個對象到GC ROOT都有必定的聯繫和路徑可達,當某個對象,對於GC ROOT不可達(即沒有人說這個東西是屬於他的)的對象,JVM則斷定爲垃圾。JVM裏稱此行爲是可達性分析。阿里雲
finalize的做用:假設一個本子已經被老媽認定爲垃圾了,但老媽在扔掉垃圾的時候必須先通過一個程序,即finalize,假如在這個程序過程當中,我忽然想起這個本子對我仍是有用的,那麼這個本子就不會被認定爲垃圾,從而繼續保留在內存中。
知道什麼是垃圾,找到了垃圾的位置,接下來的問題是我要怎麼處理這個垃圾,即垃圾回收。我要怎樣忘了你是誰,關鍵是要怎麼字,這個動做是怎麼發生的。
標記清除:在這個樓層中,垃圾四處都有,甚至散亂在非垃圾之間或者周圍,即然我老媽已經給有用的東西作個標誌,那麼這就意味着我老媽只須要清除那些沒有標識的東西。標記清除的作法形象成就是我老媽拿着垃圾桶,從頭至尾,看到垃圾就把他扔到垃圾桶裏面。這種作法無疑是最簡單的,可是帶來的後果也是很明顯的,空間碎片太多。這裏的空間碎片又要作如何理解,每一個物品(每一個對象)都是須要佔據着必定的的面積(即內存),他要站住腳跟嘛,可是若是空間碎片的太多,就會致使大的物品來臨的時候,區域(內存)不夠用,就會再次引起垃圾回收(意味着你打遊戲的時候可能要停頓個幾秒)。再舉個現實中的例子,打包行李箱的時候,隨隨便便,散亂的放置東西,行李廂很容易被撐滿,這個時候你還想放一雙鞋進去,你會發現空間不夠用,只能把因此東西都倒出來,整整齊齊的,從上到下從左到右的放置物品。對於空間的利用率,整齊的作法比散亂無章的行爲更來得高,這就引出了另一個作法,標記整理算法。
標記整理:你見過有誰掃地的時候,看到垃圾就直接把掃到掃帚了裏面,看到就掃。不存在的!人是有惰性的,全部總會找到更高效的作法,更習慣的作法是將垃圾掃到一塊兒,再統一將其扔到垃圾桶中。
複製:這個算法就有點奢侈了,無論這個內存裏有多少垃圾,我老媽都統一將他們扔掉,而後從新再買一次那些咱們還須要用的物品,俗稱複製。所以,若是存活對象太多,這個算法是不適合的(想一想就知道了-.-),其二,JVM裏面須要將可用內存分爲兩半,一半供目前使用,一半供複製後的對象使用。
未完待續……