什麼是JVM?深入解析JVM原理!

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":" 一、JVM是什麼?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"JVM是Java Virtual Machine(Java虛擬機)的縮寫,是通過在實際的計算機上仿真模擬各種計算機功能來實現的。由","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"一套字節碼指令集、一組寄存器、一個棧、一個垃圾回收堆和一個存儲方法域等","attrs":{}},{"type":"text","text":"組成。JVM屏蔽了與操作系統平臺相關的信息,使得Java程序只需要生成在Java虛擬機上運行的目標代碼(字節碼),就可在多種平臺上不加修改的運行,這也是Java能夠“","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"一次編譯,到處運行的","attrs":{}},{"type":"text","text":"”原因。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"二、JRE、JDK和JVM的關係","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"JRE(Java Runtime Environment, Java運行環境)","attrs":{}},{"type":"text","text":"是Java平臺,所有的程序都要在JRE下才能夠運行。包括JVM和Java核心類庫和支持文件。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"JDK(Java Development Kit,Java開發工具包)","attrs":{}},{"type":"text","text":"是用來編譯、調試Java程序的開發工具包。包括Java工具(javac/java/jdb等)和Java基礎的類庫(java API )。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"JVM(Java Virtual Machine, Java虛擬機)","attrs":{}},{"type":"text","text":"是JRE的一部分。JVM主要工作是解釋自己的指令集(即字節碼)並映射到本地的CPU指令集和OS的系統調用。Java語言是跨平臺運行的,不同的操作系統會有不同的JVM映射規則,使之與操作系統無關,完成跨平臺性。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下圖表示了JDK、JRE和JVM三者間的關係:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/80/80976fe9e618cc79a2aa0547535f2e6d.png","alt":"","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"總結:使用JDK(調用JAVA API)開發JAVA程序後,通過JDK中的編譯程序(javac)將Java程序編譯爲Java字節碼,在JRE上運行這些字節碼,JVM會解析並映射到真實操作系統的CPU指令集和OS的系統調用。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"三、JVM原理","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"java 體系結構介紹:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/8c/8c8c2733dad1a61e395eeb0ce8eda1ec.png","alt":"","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Class Loader(類加載器):用於裝載.class文件。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Execution Engine(執行引擎):用於執行字節碼或者本地方法。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"運行時數據區:方法區、堆、java棧、pc寄存器、本地方法棧。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1、JVM生命週期介紹","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Java實例對應一個獨立運行的Java程序(","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"進程級別","attrs":{}},{"type":"text","text":")","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"(1)","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"啓動","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"啓動一個Java程序,一個JVM實例就產生。擁有public static void main(String[] args)函數的class可以作爲JVM實例運行的起點。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"(2)","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"運行","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"main()作爲程序初始線程的起點,任何其他線程均可由該線程啓動。JVM內部有兩種線程:守護線程和非守護線程,main()屬於非守護線程,守護線程通常由JVM使用,程序可以指定創建的線程爲守護線程。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"(3)","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"消亡","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當程序中的所有非守護線程都終止時,JVM才退出;若安全管理器允許,程序也可以使用Runtime類或者System.exit()來退出。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"JVM執行引擎實例則對應了屬於用戶運行程序線程它是線程級別的。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2、Java類加載器","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Java加載類的過程","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/60/60138e7a30c226b7df4d178c0af65e02.png","alt":"","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"(1)裝載(loading)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"負責找到二進制字節碼並加載至JVM中,JVM通過類名、類所在的包名、ClassLoader完成類的加載。因此,標識一個被加載了的類:類名 + 包名 + ClassLoader實例ID。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"(2)鏈接(linking)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"負責對二進制字節碼的格式進行校驗、初始化裝載類中的靜態變量以及解析類中調用的接口。完成校驗後,JVM初始化類中的靜態變量,並將其賦值爲默認值。最後對比類中的所有屬性、方法進行驗證,以確保要調用的屬性、方法存在,以及具備訪問權限(例如private、public等),否則會造成NoSuchMethodError、NoSuchFieldError等錯誤信息。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"(3)初始化(initializing)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"負責執行類中的靜態初始化代碼、構造器代碼以及靜態屬性的初始化,以下","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"四種情況","attrs":{}},{"type":"text","text":"初始化過程會被觸發。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"①調用 new","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"②反射調用了類中的方法","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"③子類調用了初始化","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"④JVM啓動過程終止定的初始化類","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"JVM類加載順序","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"(1)層級結構","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/4a/4a0a102af2244d8c955288935ba64e65.png","alt":"","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"①Booststrap ClassLoader","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"跟ClassLoader,C++實現,JVM啓動時初始化此ClassLoader,並由此完成$JAVA_HONE中jre/lib/rt.jar(Sun JDK的實現)中所有class文件的加載,這個jar中包含了java規範定義的所有接口以及實現。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"②Extension ClassLoader","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"JVM用此classloader來加載擴展功能的一些jar包","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"③System ClassLoader","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"JVM用此ClassLoader來加載啓動參數中指定的ClassPath中的jar包以及目錄,在Sun JDK中ClassLoader對應的類名爲AppClassLoader。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"④User-Defined ClassLoader","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"User-Defined ClassLoader是Java開發人員繼承ClassLoader抽象類實現的ClassLoader,基於自定義的ClassLoader可用於加載非ClassPath中的jar以及目錄。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"(2)委派模式(Delegation Mode)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/cc/cc82140b9dd04ccc95a17b864914439b.png","alt":"","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當JVM加載一個類的時候,下層的加載器會將任務給上一層類加載器,上一層加載檢查它的命名空間中是否已經加載這個類,如果已經加載,直接使用這個類。如果沒有加載,繼續往上委託直到頂部。檢查之後,按照相反的順序進行加載。如果Bootstrap加載器不到這個類,則往下委託,直到找到這個類。一個類可以被不同的類加載器加載。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可見性限制:下層的加載器能夠看到上層加載器中的類,反之則不行,","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"委派只能從下到上","attrs":{}},{"type":"text","text":"。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不允許卸載類:類加載器可以加載一個類,但不能夠卸載一個類。但是類加載器可以被創建或者刪除。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"(3)JVM執行引擎","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"類加載器將字節碼載入內存後,執行引擎以java字節碼爲單元,讀取java字節碼。java字節碼機器讀不懂,必須將字節碼轉化爲平臺相關的機器碼。這個過程就是由執行引擎完成的。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/ea/ea4faad7036c0e5855c9784bdc993993.png","alt":"","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在執行方法時JVM提供了四種指令來執行","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"①invokestatic:調用類的static方法。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"②invokevirtual:調用對象實例的方法。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"③invokeinterface:將屬性定義爲接口來進行調用。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"④invokespecial:JVM對於初始化對象(Java構造器的方法爲:)以及調用對象實例的私有方法時。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"主要的執行計數:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"解釋,即時執行,自適應優化、芯片級直接執行。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"解釋屬於第一代JVM","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"即時編譯JIT屬於第二代JVM","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"自適應優化","attrs":{}},{"type":"text","text":"(目前sun的HotspotJVM採用這種技術),吸取第一代JVM和第二代JVM的經驗,採用兩者結合的方式,開始對所有的代碼都採用解釋執行的方式,並監視代碼執行情況,然後對那些經常調用的方法啓動一個後臺線程,將其編譯爲本地代碼,並進行優化。若方法不再頻繁使用,則取消編譯過代碼,仍對其進行解釋執行。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3、java運行時數據區","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/91/9151d6617710de095d5a1770d2398528.png","alt":"","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"4、PC寄存器","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"用於存儲每個線程下一步將要執行的JVM指令,若該方法爲native的,則PC寄存器中不存儲任何信息。Java多線程情況下,每個線程都有一個自己的PC,以便完成不同線程上下文環境的切換。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"5、JVM棧","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"JVM棧是線程私有的,每個線程創建的同時都會創建JVM棧,JVM棧中存放當前線程中局部基本類型的變量(Java中定義的八種基本類型:boolean、char、byte、short、int、long、float、double)、部分的返回結果以及Stack Frame,非基本類型的對象在JVM棧上僅存放一個指向堆的地址。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"6、堆(Heap)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"它是JVM用來存儲對象實例以及數組值的區域,可以認爲Java中所有通過new創建的對象的內存都在此分配,Heap中的對象的內存需要等待GC進行回收。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"堆在JVM啓動的時候就被創建,堆中儲存了各種對象,這些對象被自動管理內存系統(Automatic Storage Management System),也就是常說的“Garbage Collector(垃圾回收器)”管理。這些對象無需、也無法顯示地被銷燬。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"JVM將Heap分爲兩塊:新生代New Generation和舊生代Old Generation","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/09/091c32e0f1ea261c35e2a69e5a53840a.png","alt":"","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"堆是JVM中所有線程共享的,因此在其上進行對象內存的分配均需要進行加鎖,導致new對象的開銷比較大。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Sun Hotspot JVM爲了提升對象內存分配的效率,對於所有創建的線程都會分配一塊獨立的空間TLAB(Thread Local Allocation Buffer),其大小由JVM根據運行的情況計算而得,在TLAB上分配對象時不需要加鎖,因此JVM在給線程對象分配內存時會盡量的在TLAB上分配,在這種情況下JVM中分配對象內存的性能和C基本是一樣的,但如果對象過大的話則仍然要直接使用堆空間分配。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"TLAB僅作用於新生代的Eden Space,因此在編寫Java程序時,通常多個小的對象比大的對象分配起來更加高效。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所有新創建的Object都將會存儲在新生代Young Generation中。如果Young Generation的數據在一次或多次GC後存活下來,那麼將被轉移到OldGeneration。新的Object總是創建在Eden Space。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"7、方法區域(Method Area)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在Sun JDK中這塊區域對應的爲PermanetGeneration,又稱爲持久代。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"方法區域存放所加載類的信息(名稱、修飾符等)、類中的靜態變量、類中定義爲final類型的常量、類中的Field信息、類中的方法信息,當開發人員在程序中通過Class對象中的getName,isInstance等方法來獲取信息時,這些數據都來源於方法區域,同時方法區域也是","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"全局共享","attrs":{}},{"type":"text","text":"的,在一定條件下它也會被GC,當方法區域需要使用的內存超過其允許的大小時,就會拋出OutOfMemory的錯誤信息。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"8、運行時常量池(Runtime Constant Pool)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"存放的爲類中的固定常量信息、方法和Field的引用信息等,其空間從方法區域中分配。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"9、本地方法堆棧(Native Method Stacks)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"JVM採用本地方法堆來支持native方法的執行,此區域用於存儲每個native方法調用的狀態。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"10、JVM垃圾回收","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"GC的基本原理","attrs":{}},{"type":"text","text":":將內存中不再被使用的對象進行回收,GC中用於回收的方法稱爲收集器,由於GC需要消耗一些資源和時間,Java在對對象生命週期特徵進行分析後,按照新生代、舊生代的方式來對對象進行收集,以儘可能的縮短GC對應用造成的暫停。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對新生代的對象收集稱爲minor GC","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對舊生代的對象收集稱爲Full GC","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"程序中主動調用System.gc()強制執行的GC爲Full GC。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"不同的對象引用類型,GC會採用不同的方法進行回收,JVM對象的引用分爲了四種類型","attrs":{}},{"type":"text","text":":","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"①強引用:默認情況下,對象採用的均爲強引用(這個對象的實例沒有其他對象引用時, GC時纔會被回收)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"②軟引用:軟引用是Java中提供的一種比較適合於緩存場景的應用(只有內存不夠的情況下才會被GC)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"③弱引用:在GC時一定會被GC回收。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"④虛引用:虛引用只是用來得知對象是否被GC。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​","attrs":{}}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章