深入理解jvm虚拟机(面试复习)
java運行時數據區
類的加載過程
雙親委派機制
程序計數器
虛擬機棧
棧幀結構
紅色區域:線程共享
灰色區域:線程私有
類的加載過程
- 加載: 就是將我們編譯后的.class文件從磁盤加載到內存。更準確的說是應該加載到我們的方法區當中。jdk7之前方法區的實現是永久代,jdk7之后方法區叫元空間。
加載通過類加載器來完成,類加載器有兩種,引導類(啟動類)加載器(C/C++語言實現),自定義類加載器。將所有派生于ClassLoader的類加載器都劃分為自定義類加載器,而引導類加載器(Bootstrap ClassLoader)并沒有繼承ClassLoader類,用來加載Java核心庫中的信息,同時自定義加載器也是有引導類加載器加載。自定義類加載器又分為:Extension Class Loader(擴展類加載器),System Class Loader(AppClassLoader)(系統類加載器),用戶自定義加載器。擴展類加載器主要加載ext子目錄下的內容。系統類加載器加載程序員自己寫的類。其中擴展類加載器為系統類加載器的父加載器,引導類加載器為擴展類加載器的父加載器,這里的父子關系不能理解為Java類的父子繼承關系,可以理解為上下級的關系。 最終類的加載是通過那種類型的加載器去執行,有jvm通過雙親委派機制來確定。 - 鏈接(驗證,準備,解析)
- 驗證:保證被加載類的安全性。
- 準備:
- 為類變量(static修飾的成員變量)設置初始值,即零值。并且在jdk1.8之后,類變量會隨著Class對象一起存放在java堆中。
- javac會為被final修飾的變量生成ConstantValue屬性,在準備階段虛擬機會根據ConstantValue屬性為變量賦值。
- 不會為實例變量分配初始值,實例變量會隨著對象的實例化一起存放到java堆中。
- 解析:將常量池中的符號引用轉換為直接引用
- 初始化
就是執行類構造器方法<clinit>()的過程。此方法不同于類的構造器,構造器是虛擬機視角下的<init>()方法。<clinit>()方法不是自定義的,是javac編譯器為收集所有對類變量賦值操作的方法,也就是說如果當前類中如果沒有類變量,也就沒有<clinit>()。若該類具有父類,jvm會保證子類的<clinit>()執行前,父類的<clinit>()已經執行完畢。
雙親委派機制
如果一個類加載器收到了類加載的請求,它會將加載類的任務委托給父類加載器,如果父類加載器還存在父類加載器,繼續向上層委托,直到啟動類加載器。如果在這個過程中發現當前加載器可以執行加載任務,而當前類加載器的父加載器無法執行加載任務,那么就確定了加載任務的執行者。
雙親委派機制優勢
- 避免類的重復加載,確保一個類的全局唯一性。
- 保護程序安全,防止核心API被隨意篡改。(也叫沙箱安全機制)
程序計數器(pc寄存器)
程序計數器:程序計數器記錄的是當前線程的當前方法的下一條要執行的JVM指令地址。如果執行的方法為native(本地方法),程序計數器將不指定值。程序計數器又叫pc寄存器,這里的pc寄存器并非是廣義上所指的物理寄存器,是對物理pc寄存器的一種抽象模擬。程序計數器是java運行時數據區唯一一個不存在內存溢出的模塊。
虛擬機棧
棧管運行,堆管存儲。虛擬機棧主管java程序的運行,它保存方法的局部變量,部分結果,并參與方法的調用和返回,生命周期的線程一致。如果方法中的局部變量為引用類型,則存儲的是引用類型變量的地址值。每個方法的調用與結束對應著一次入棧與出棧操作。注意:對棧來說,不存在垃圾回收的問題。所以應該盡量避免出現OOM(內存溢出)的情況。
棧幀結構
-
局部變量表
局部變量表是一個數組結構,在編譯后就已經確定了數組的長度。主要用來存放方法參數以及定義在方法體內的局部變量,并且局部變量表所需要的容量大小是在編譯器確定下來的,在運行期不會改變局部變量表的大小。slot(變量槽) 是局部變量表最基本的存儲單元。一個32位以內的基本數據類型只占用一個slot,一個引用數據類型也只占用一個slot。64為的基本數據類型(long,double)占用兩個slot。要注意靜態方法無法使用this關鍵字,因為靜態方法中沒有傳入this,而非靜態方法默認會傳入this。同時局部變量必須進行顯示賦值,否則編譯不通過。局部變量表中的變量也是重要的垃圾回收根節點,只要被局部變量表中直接或間接引用的對象都不會被回收。- slot(變量槽) 可以重復利用,如果一個局部變量過了其作用域,那么在其作用域之后聲明的新的局部變量就很可能會復用過期局部變量的槽位,從而達到節省資源的目的。
-
操作數棧
操作數棧遵循后進先出的模式,又叫表達式棧。操作數棧的深度在編譯后就已經確定了。32位的數據類型占用一個棧的深度,64位的類型占兩個棧的深度。在方法的執行過程中,根據字節碼指令,往棧中寫入數據或提取數據。如果被調用的方法帶有返回值,其返回值也會被壓入當前棧幀的操作數棧中。- 棧頂緩存技術: Hotspot虛擬機是基于棧式架構的虛擬機,他的可移植性好,能夠更好的實現跨平臺。但是相較于基于寄存器式架構的虛擬機,他的指令更多,執行速度慢,因為需要頻繁的執行內存的讀寫操作。棧頂緩存技術為了提高執行引擎的執行效率,將棧頂元素全部緩存在屋里cpu的寄存器中,以降低對內存的讀寫次數。
-
幀數據區
- 動態鏈接
指向運行時常量池中的方法引用。(常量池在class文件中,運行時常量池在方法區)- 方法調用
在方法的執行過程中,需要將符號引用轉換為調用方法的直接引用。如果符號引用轉換為調用方法的直接引用是在編譯器確定下來的,這個轉換過程就叫靜態鏈接。對應方法的綁定機制為早期綁定。如果實在運行期間確定下來的,那么這個過程就叫動態鏈接。對應方法的綁定機制叫晚期綁定。
- 方法調用
- 方法返回地址
存放調用該方法的pc寄存器的值。 - 附加信息
- 動態鏈接
總結
以上是生活随笔為你收集整理的深入理解jvm虚拟机(面试复习)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【pytorch】LSTM神经网络
- 下一篇: 手机pdf文件转语音_录音语音转文字手机