JVM是Java Virual Machine(Java虛擬機)的縮寫,是一個虛擬計算機。Java源文件經編譯成字節碼程序,經過JVM將每一條指令翻譯成不一樣平臺的機器碼,經過特定平臺運行。算法
JVM屏蔽了與具體操做系統平臺相關的信息,Java程序只需生成在Java虛擬機上運行的字節碼,就能夠在多種平臺上不加修改的運行。所謂"一次編譯,屢次運行",編譯出的字節碼文件.class。數組
類加載器:加載class文件;緩存
執行引擎:執行字節碼或者執行本地方法多線程
運行時數據區:包括方法區、堆、棧、PC寄存器、本地方法棧併發
PC計數器:用於存儲每一個線程下一條字節碼指令地址;jvm
棧:線程私有,生命週期和線程一致。描述的是 Java 方法執行的內存模型:每一個方法在執行時都會建立一個棧幀(Stack Frame)用於存儲局部變量表
、操做數棧
、動態連接
、方法出口
等信息。每個方法從調用直至執行結束,就對應着一個棧幀從虛擬機棧中入棧到出棧的過程。工具
堆:線程共享,主要是存放對象實例和數組。能夠認爲Java中全部經過new建立的對象的內存都在此分配,Heap中的對象的內存須要等待GC進行回收。性能
方法區:屬於全局共享內存區域,存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據。學習
本地方法棧:區別於 Java 虛擬機棧的是,Java 虛擬機棧爲虛擬機執行 Java 方法(也就是字節碼)服務,而本地方法棧則爲虛擬機使用到的 Native 方法服務。開發工具
運行時常量池:存放類中固定的常量信息、方法和Field的引用信息等,其空間是從方法區中分配。
引用計數法:給對象中添加一個引用計數器,當一個地方引用了對象,計數加1;當引用失效,計數器減1;當計數器爲0表示該對象已死、可回收;但很難解決循環引用問題;
可達性分析:經過一系列稱爲「GC Root」的對象做爲起點,從這些節點開始向下搜索,搜索所走過的路徑稱爲引用鏈,當一個對象到GC Roots沒有任何引用鏈相連(從 GC Roots 到這個對象不可達)時,則證實此對象已死、可回收。
即便在可達性分析算法中不可達的對象,也並不是是「facebook」的,這時候它們暫時出於「緩刑」階段,一個對象的真正死亡至少要經歷兩次標記過程:若是對象在進行中可達性分析後發現沒有與 GC Roots 相鏈接的引用鏈,那他將會被第一次標記而且進行一次篩選,篩選條件是此對象是否有必要執行 finalize() 方法。當對象沒有覆蓋 finalize() 方法,或者 finalize() 方法已經被虛擬機調用過,虛擬機將這兩種狀況都視爲「沒有必要執行」。
若是這個對象被斷定爲有必要執行 finalize() 方法,那麼這個對象竟會放置在一個叫作 F-Queue 的隊列中,並在稍後由一個由虛擬機自動創建的、低優先級的 Finalizer 線程去執行它。這裏所謂的「執行」是指虛擬機會出發這個方法,並不承諾或等待他運行結束。finalize() 方法是對象逃脫死亡命運的最後一次機會,稍後 GC 將對 F-Queue 中的對象進行第二次小規模的標記,若是對象要在 finalize() 中成功拯救本身 —— 只要從新與引用鏈上的任何一個對象簡歷關聯便可。
finalize() 方法只會被系統自動調用一次。
直接標記清除就可。
兩個不足:
把空間分紅兩塊,每次只對其中一塊進行 GC。當這塊內存使用完時,就將還存活的對象複製到另外一塊上面。
解決前一種方法的不足,可是會形成空間利用率低下。
不一樣於針對新生代的複製算法,針對老年代的特色,建立該算法。主要是把存活對象移到內存的一端。
根據存活對象劃分幾塊內存區,通常是分爲新生代和老年代。而後根據各個年代的特色制定相應的回收算法。
新生代:每次垃圾回收都有大量對象死去,只有少許存活,選用複製算法比較合理。
老年代:老年代中對象存活率較高、沒有額外的空間分配對它進行擔保。因此必須使用 標記 —— 清除 或者 標記 —— 整理 算法回收。
對象優先在 Eden 分配
大對象直接進入老年代
長期存活的對象將進入老年代