JVM --- 筆記

虛擬機

java8API地址https://docs.oracle.com/javase/8/docs/api/

jvm8 地址https://docs.oracle.com/javase/specs/jvms/se8/html/

在這裏插入圖片描述

一、類加載子系統

在這裏插入圖片描述

(一)類的加載過程

1.加載階段(將類以二進制流形式加載到JVM方法區中生成Class對象。)

(1)通過一個類的全限定名獲取定義此類的二進制字節流。

(2)將字節流所代表的靜態存儲結構轉爲方法區的運行時數據結構。

(3)在內存中生成代表此類的java.lang.Class對象,作爲方法區中這個類的訪問入口。

2.鏈接階段

(1)驗證(Verify)

**確保字節流文件信息符合虛擬機規範,**保證類加載準確性,有格式、元數據、字節碼驗證等。

(2) 準備(Prepare)

爲類變量分配內存,初始化零值。(Static修飾的變量)

這裏不包含final修飾的static,因爲final修飾的會在編譯時就分配了。準備階段顯示初始化。

類變量分配在方法區,實例變量隨對象一起分配在堆內存。這裏不會爲實例變量分配初始化。

(3)解析(Resolve)

將常量池中的符號引用轉爲直接引用。

3. 初始化

執行類構造器方法()的過程。此方法不需要定義,時虛擬機視角下的。此時會給類變量顯示賦值。

一個類只能被加載一次。會被同步加鎖。

(二)類加載器的分類

在這裏插入圖片描述

在這裏插入圖片描述

1.虛擬機自帶的加載器

在這裏插入圖片描述

啓動類加載器 (Bootstrap Class Loader)
  • 該類由c/c++實現。嵌套在jvm中。
  • 用來加載java的核心類庫,用於提供JVM自身需要的類。
  • 並不繼承java.lang.ClassLoader,沒有父加載器。
  • 只加載java、javax、sun等開頭的類(核心類庫)
應用程序類加載器(System Class Loader)
  • java語言編寫,由sun.misc.Launcher$AppClassLoader實現。

在這裏插入圖片描述

擴展類加載器(Extension Class Loader)
  • java語言編寫。
用戶自定義類加載器

什麼情況下使用

  • 隔離加載類 不同框架整合在一起,中間件等,會存在類的衝突,使用該方式隔離框架之間、中間件之間隔離
  • 防止源碼泄露。

(三) 類的雙親委派機制

在這裏插入圖片描述

1. 工作原理

類加載器收到類加載請求,首先向上找其父類,直到找到引導類,看起是否可以加載,不能則從引導類往下的子類進行嘗試。

這樣做的目的是類的加載首先去java核心類庫中找是否有,核心類庫的優先級最高,依次往下。

2. 優勢

  • 避免類的重複加載。
  • 保護程序安全性,防止核心API被篡改。
    • eg:自定義的java.lang.String 是不會被加載的。
    • eg:自定義的java.lang.Maotao 加載會報錯。自己定義和核心類庫的包名一致,爲了保護引導類加載器,會拋出安全異常。

3. 沙箱安全機制

保證核心API源代碼的保護,引導類加載器只加載核心API,不加載自定義的與核心API同名或同包名的API。

(四)其他

jvm中比較兩個calss是否爲同一類,存在兩個必要條件:

  • 類的完整類名必須一致,包括包名。
  • 類的類加載器必須一致。

二、 運行時數據區

在這裏插入圖片描述

灰色的PC程序計數器、本地方法棧、虛擬機棧是屬於線程私有的。

紅色的方法區和堆是屬於進程的,同一個進程內的線程共享該內存。

線程

線程是一個程序裏的運行單元。JVM允許一個應用有多個線程並行執行。

在Hotspot中,java線程與操作系統的本地線程是有直接映射關係。一一對應。

(一)PC程序寄存器

作用: 用來存儲指向下一條指令的地址。行號的表示。

生命週期 : 線程私有,生命週期與線程一致。

執行:任何時間,一個線程只執行一個方法,程序計數器會保存當前正在執行方法的JVM指令地址。若執行本地方法則爲空。

無OutMemoryError情況:Java虛擬機規範中唯一一個不會內存溢出的內存。