JVM虛擬機結構:
1.類加載器(ClassLoader):在JVM啟動時或者在類運行時將需要的class加載到JVM中。
類加載器類型:
BootStrapClassLoader。它是最頂層的類加載器,是由C++編寫而成,已經內嵌到JVM中了。
在JVM啟動時會初始化該ClassLoader,它主要用來讀取java的核心類庫JRE/lib/rt.jar中所有的class文件,這個jar文件中包含了java規范定義的所有接口及實現。
ExtensionClassLoader。它是用來讀取Java的一些擴展類庫,如讀取JRE/lib/ext/*.jar中的包等(這里要注意,有些版本的是沒有ext這個目錄的)。
AppClassLoader。它是用來讀取CLASSPATH下指定的所有jar包或目錄的類文件,一般情況下這個就是程序中默認的類加載器。
CustomClassLoader。它是用戶自定義編寫的,它用來讀取指定類文件 。
基于自定義的ClassLoader可用于加載非Classpath中(如從網絡上下載的jar或二進制)的jar及目錄、還可以在加載前對class文件優一些動作,如解密、編碼等。
注意:ExtClassLoader的父類加載器是null,只不過在默認的ClassLoader的 loadClass方法中,當parent為null時,是交給BootStrapClassLoader來處理的,而且ExtClassLoader沒有重寫默認的loadClass方法,
所以,ExtClassLoader也會調用BootStrapLoader類加載器來加載,這就導致“BootStrapClassLoader具備了ExtClassLoader父類加載器的功能”
類加載器主要方法:
loadClass。classloader加載類的入口,此方法負責加載指定名字的類,ClassLoader的實現方法為先從已經加載的類中尋找,如沒有則繼續從父ClassLoader中尋找,如仍然沒找到,則從BootstrapClassLoader中尋找,
最后再調用findClass方法來尋找,如要改變類的加載順序,則可覆蓋此方法,如加載順序相同,則可通過覆蓋findClass來做特殊的處理,例如解密、固定路徑尋找等,當通過整個尋找類的過程仍然未獲取到Class對象時,
則拋出ClassNotFoundException。如類需要resolve,則調用resolveClass進行鏈接。
findClass。此方法直接拋出ClassNotFoundException,因此需要通過覆蓋loadClass或此方法來以自定義的方式加載相應的類。
defineClass。此方法負責將二進制的字節碼轉換為Class對象,這個方法對于自定義加載類而言非常重要,如二進制的字節碼的格式不符合JVM Class文件的格式,拋出ClassFormatError;
如需要生成的類名和二進制字節碼中的不同,則拋出NoClassDefFoundError;如需要加載的class是受保護的、采用不同簽名的或類名是以java.開頭的,則拋出SecurityException;
如需加載的class在此ClassLoader中已加載,則拋出LinkageError。
2.執行引擎:負責執行class文件中包含的字節碼指令(執行引擎的工作機制,這里也不細說了,這里主要介紹JVM結構);
3.內存區(也叫運行時數據區):是在JVM運行的時候操作所分配的內存區。運行時內存區主要可以劃分為5個區域,如圖:
方法區(Method Area):用于存儲類結構信息的地方,包括常量池、靜態變量、構造函數等。雖然JVM規范把方法區描述為堆的一個邏輯部分,
但它卻有個別名non-heap(非堆),所以大家不要搞混淆了。方法區還包含一個運行時常量池。
java堆(Heap):存儲java實例或者對象的地方。這塊是GC的主要區域(后面解釋)。從存儲的內容我們可以很容易知道,方法區和堆是被所有java線程共享的。
java棧(Stack):java棧總是和線程關聯在一起,每當創建一個線程時,JVM就會為這個線程創建一個對應的java棧。
在這個java棧中又會包含多個棧幀,每運行一個方法就創建一個棧幀,用于存儲局部變量表、操作棧、方法返回值等。
每一個方法從調用直至執行完成的過程,就對應一個棧幀在java棧中入棧到出棧的過程。所以java棧是 現成私有的。
程序計數器(PC Register):用于保存當前線程執行的內存地址。由于JVM程序是多線 程執行的(線程輪流切換),
所以為了保證線程切換回來后,還能恢復到原先狀態,就需要一個獨立的計數器,記錄之前中斷的地方,可見程序計數器也是線程私有的。
本地方法棧(Native Method Stack):和java棧的作用差不多,只不過是為JVM使用到的native方法服務的。
4.本地方法接口:主要是調用C或C++實現的本地方法及返回結果。
JVM GC:
將對象按其生命周期的不同劃分成:年輕代(Young Generation)、年老代(Old Generation)、持久代(Permanent Generation)
檢測出垃圾
引用計數法
可達性分析算法
年輕代:涉及了復制算法;年老代:涉及了“標記-整理(Mark-Sweep)”的算法。
JVM調優:
從以下幾個方面進行:
線程池:解決用戶響應時間長的問題
連接池
JVM啟動參數:調整各代的內存比例和垃圾回收算法,提高吞吐量
程序算法:改進程序邏輯算法提高性能
新聞熱點
疑難解答