JVM架构和GC垃圾回收机制--面试
JVM架構和GC垃圾回收機制詳解
JVM架構圖分析
下圖:參考網絡+書籍,如有侵權請見諒?(想了解Hadoop內存溢出請看:?Hadoop內存溢出(OOM)分類、參數調優化)
JVM被分為三個主要的子系統
(1)類加載器子系統(2)運行時數據區(3)執行引擎
1. 類加載器子系統
Java的動態類加載功能是由類加載器子系統處理。當它在運行時(不是編譯時)首次引用一個類時,它加載、鏈接并初始化該類文件。
1.1?加載
類由此組件加載。啟動類加載器?(BootStrap class Loader)、擴展類加載器(Extension class Loader)和應用程序類加載器(Application class Loader)?這三種類加載器幫助完成類的加載。
1.??啟動類加載器?–?負責從啟動類路徑中加載類,無非就是rt.jar。這個加載器會被賦予最高優先級。
2.??擴展類加載器?–?負責加載ext?目錄(jre\lib)內的類.
3.??應用程序類加載器?–?負責加載應用程序級別類路徑,涉及到路徑的環境變量等etc.
上述的類加載器會遵循委托層次算法(Delegation Hierarchy Algorithm)加載類文件。
1.2?鏈接
1.??校驗?– 字節碼校驗器會校驗生成的字節碼是否正確,如果校驗失敗,我們會得到校驗錯誤。
2.??準備?–?分配內存并初始化默認值給所有的靜態變量。
3.??解析?–?所有符號內存引用被方法區(Method Area)的原始引用所替代。
1.3?初始化
這是類加載的最后階段,這里所有的靜態變量會被賦初始值,?并且靜態塊將被執行。
2.?運行時數據區(Runtime Data Area)
The 運行時數據區域被劃分為5個主要組件:
2.1 方法區(Method Area)
所有類級別數據將被存儲在這里,包括靜態變量。每個JVM只有一個方法區,它是一個共享的資源。
2.2 堆區(Heap Area)
所有的對象和它們相應的實例變量以及數組將被存儲在這里。每個JVM同樣只有一個堆區。由于方法區和堆區的內存由多個線程共享,所以存儲的數據不是線程安全的。
2.3 棧區(Stack Area)
對每個線程會單獨創建一個運行時棧。對每個函數呼叫會在棧內存生成一個棧幀(Stack Frame)。所有的局部變量將在棧內存中創建。棧區是線程安全的,因為它不是一個共享資源。棧幀被分為三個子實體:
a 局部變量數組?–?包含多少個與方法相關的局部變量并且相應的值將被存儲在這里。
b 操作數棧?–?如果需要執行任何中間操作,操作數棧作為運行時工作區去執行指令。
c 幀數據?– 方法的所有符號都保存在這里。在任意異常的情況下,catch塊的信息將會被保存在幀數據里面。
2.4 PC寄存器
每個線程都有一個單獨的PC寄存器來保存當前執行指令的地址,一旦該指令被執行,pc寄存器會被更新至下條指令的地址。
2.5 本地方法棧
本地方法棧保存本地方法信息。對每一個線程,將創建一個單獨的本地方法棧。
3. 執行引擎
分配給運行時數據區的字節碼將由執行引擎執行。執行引擎讀取字節碼并逐段執行。
3.1? 解釋器:
?解釋器能快速的解釋字節碼,但執行卻很慢。 解釋器的缺點就是,當一個方法被調用多次,每次都需要重新解釋。
編譯器
JIT編譯器消除了解釋器的缺點。執行引擎利用解釋器轉換字節碼,但如果是重復的代碼則使用JIT編譯器將全部字節碼編譯成本機代碼。本機代碼將直接用于重復的方法調用,這提高了系統的性能。
a.?中間代碼生成器?– 生成中間代碼
b.?代碼優化器?– 負責優化上面生成的中間代碼
c.?目標代碼生成器?– 負責生成機器代碼或本機代碼
d.??探測器(Profiler)?– 一個特殊的組件,負責尋找被多次調用的方法。
3.3? 垃圾回收器:
收集并刪除未引用的對象??梢酝ㄟ^調用"System.gc()"來觸發垃圾回收,但并不保證會確實進行垃圾回收。JVM的垃圾回收只收集哪些由new關鍵字創建的對象。所以,如果不是用new創建的對象,你可以使用finalize函數來執行清理。
Java本地接口 (JNI):?JNI?會與本地方法庫進行交互并提供執行引擎所需的本地庫。
本地方法庫:它是一個執行引擎所需的本地庫的集合。
JVM三大核心區域
通過一個小程序認識JVM
?package com.spark.jvm; /*** 從JVM調用的角度分析java程序堆內存空間的使用:* 當JVM進程啟動的時候,會從類加載路徑中找到包含main方法的入口類HelloJVM* 找到HelloJVM會直接讀取該文件中的二進制數據,并且把該類的信息放到運行時的Method內存區域中。* 然后會定位到HelloJVM中的main方法的字節碼中,并開始執行Main方法中的指令* 此時會創建Student實例對象,并且使用student來引用該對象(或者說給該對象命名),其內幕如下:* 第一步:JVM會直接到Method區域中去查找Student類的信息,此時發現沒有Student類,就通過類加載器加載該Student類文件;* 第二步:在JVM的Method區域中加載并找到了Student類之后會在Heap區域中為Student實例對象分配內存,* 并且在Student的實例對象中持有指向方法區域中的Student類的引用(內存地址);* 第三步:JVM實例化完成后會在當前線程中為Stack中的reference建立實際的應用關系,此時會賦值給student* 接下來就是調用方法* 在JVM中方法的調用一定是屬于線程的行為,也就是說方法調用本身會發生在線程的方法調用棧:* 線程的方法調用棧(Method Stack Frames),每一個方法的調用就是方法調用棧中的一個Frame,* 該Frame包含了方法的參數,局部變量,臨時數據等 student.sayHello();*/ public class HelloJVM {//在JVM運行的時候會通過反射的方式到Method區域找到入口方法mainpublic static void main(String[] args) {//main方法也是放在Method方法區域中的/*** student(小寫的)是放在主線程中的Stack區域中的* Student對象實例是放在所有線程共享的Heap區域中的*/Student student = new Student("spark");/*** 首先會通過student指針(或句柄)(指針就直接指向堆中的對象,句柄表明有一個中間的,student指向句柄,句柄指向對象)* 找Student對象,當找到該對象后會通過對象內部指向方法區域中的指針來調用具體的方法去執行任務*/student.sayHello();} }class Student {// name本身作為成員是放在stack區域的但是name指向的String對象是放在Heap中private String name;public Student(String name) {this.name = name;}//sayHello這個方法是放在方法區中的public void sayHello() {System.out.println("Hello, this is " + this.name);} }MapReduce過程詳解及其性能優化
轉發:https://blog.csdn.net/aijiudu/article/details/72991993
總結
以上是生活随笔為你收集整理的JVM架构和GC垃圾回收机制--面试的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: AD20学习笔记5---PCB设计规则设
- 下一篇: MAX DotNet 透明界面效果代码实
