JVM---類載入子系統
阿新 • • 發佈:2022-03-25
/** * 【JVM-類載入子系統-作用】 * 負責 從檔案系統 或 網路中載入class檔案; * ClassLoader 只負責 class檔案的載入,至於 是否可以執行,由 Execution Engine決定; * 載入的 類元資料資訊 存放於 方法區的記憶體空間; * (除了類元資料資訊外,方法區還會存放執行時常量池資訊:字串字面量、數字常量[這部分常量資訊 是class檔案中常量池部分的記憶體對映]) */
/** * 【JVM-類載入子系統-類載入】 * 載入loading: * a,通過 類的全限定名 獲取定義此類的 二進位制位元組流; * 載入class檔案方式: * 本地檔案系統; * 網路; * jar,war,zip包... * 執行時計算生成:動態代理... * 其他檔案生成:JSP * ... * * b,將 定義類的 靜態儲存結構 轉化為 方法區的執行時資料結構; * c,在 記憶體中 生成一個代表 該類的java.lang.Class物件,作為 方法區 這個類的各種元資料資訊 的訪問入口; * * * 連結linking: * a,驗證verify: * 檔案格式校驗 * 開頭是否以0xCAFEBABE * ... * 元資料驗證 * 進行語義分析:是否有父類?是否繼承final類?... * 位元組碼驗證 * 符號引用驗證 * * b,準備prepare: * 為 static變數 在方法區 分配記憶體,並 賦初始值; * 對於 final static 變數,編譯時就已經設定初始值,準備階段 顯式 初始化; * * c,解析resolve: * 將 常量池 中的 符號引用 轉化為 直接引用; * * * 初始化initialization: * 執行 <clinit>() 的過程; * * <clinit>(): * 1、來源: * javac編譯器 自動收集 類中 所有 static 變數的 賦值內容 (包括 static{} 的內容); * * 2、指令執行順序 : * 宣告順序 ; * eg: * static { * a = 2; * System.out.println(a); // 報錯:非法前向引用 * } * * private static int a = 1; * * 先使用-後宣告: * static變數a 在linking-prepare時 已經賦初始值0,所以 初始化階段執行<clinit>() 是可以的; * 【僅允許賦值,不允許呼叫】; * * <clinit>(): * iconst_2 * putstatic * iconst_1 * putstatic * return * * 3、如果 類 中沒有 static 變數 、沒有 static 程式碼塊, javac編譯後不會生成 <clinit>(); * <init> : * 類的構造器; * 任何一個類聲明後,內部至少存在一個類的構造器; * * 4、執行 子類的 <clinit>() 前 ,必須 保證 父類的<clinit>()執行完畢; * * 5、JVM 必須 保證 一個類的<clinit>() 在多執行緒 下 被 同步加鎖; * */
/** * 【JVM-類載入子系統-類載入器】 * JVM支援2種類型的類載入器: * 引導類載入器Bootstrap ClassLoader: * 自定義類載入器: * JVM規範中,將所有派生於ClassLoader的類載入器 稱為 自定義類載入器; * * sun.misc.Launcher 是一個JVM的入口應用; * public class Launcher { * static class AppClassLoader extends URLClassLoader {} * * static class ExtClassLoader extends URLClassLoader {} * } * * java.net.URLClassLoader * public class URLClassLoader extends SecureClassLoader implements Closeable {} * * java.security.SecureClassLoader * public class SecureClassLoader extends ClassLoader {} * * java.lang.ClassLoader * public abstract class ClassLoader {} * * * 引導類載入器、拓展類載入器、系統類載入器、使用者自定義類載入器 的關係: * 包含關係 (不是上下層、不是繼承關係) * * 類載入器之間的這種層級關係,稱為 類載入器的雙親委派模型; * 雙親委派模型 要求 除了頂層的啟動類載入器外,其餘的類載入器應有自己的父類載入器; * 父子關係不會以繼承的關係實現,而是使用組合關係來複用父類載入器; * * a,引導類載入器Bootstrap ClassLoader * 使用 C/C++實現,巢狀在JVM內部; * 不繼承自java.lang.ClassLoader,無父類載入器; * 載入 拓展類載入器 、系統類載入器; * 出於安全考慮,Bootstrap ClassLoader只加載java、javax、sun等開頭的類; * 作用: * 載入 Java的核心類庫 * (java_home/jre/lib/rt.jar、resources.jar或sun.boot.class.path路徑下的內容) * 用於JVM自身需要的類; * * URL[] urLs = sun.misc.Launcher.getBootstrapClassPath().getURLs(); * for(URL url : urLs){ * System.out.println(url.toExternalForm()); * } * * //file:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/resources.jar * //file:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/rt.jar * //file:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/sunrsasign.jar * //file:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/jsse.jar * //file:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/jce.jar * //file:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/charsets.jar * //file:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/jfr.jar * //file:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/classes * * b,拓展類載入器ExtClassLoader * 使用Java實現,sun.misc.Launcher.ExtClassLoader; * 繼承自ClassLoader; * 作用: * 載入 jre/lib/ext 目錄下的類庫; * * String property = System.getProperty("java.ext.dirs"); * for(String path : property.split(":")){ * System.out.println(path); * } * * // /Users/an/Library/Java/Extensions * // /Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/ext * // /Library/Java/Extensions * // /Network/Library/Java/Extensions * // /System/Library/Java/Extensions * // /usr/lib/java * * * c,系統類載入器 * 使用Java實現,sun.misc.Launcher.AppClassLoader; * 繼承自ClassLoader; * 作用: * 載入 classpath或java.class.path 下 使用者 自定義類; * * d,使用者自定義類載入器 * 為什麼要自定義? * a,隔離 載入類; * b,修改 類的載入方式; * c,拓展 載入源; * d,防止 原始碼洩漏; * * 自定義步驟: * 第一種: * a,繼承 java.lang.ClassLoader * b,重寫 findClass() * * 第二種: * 如果沒有過多的邏輯,可以直接 繼承 java.net.URLClassLoader; * * java.lang.ClassLoader * public abstract class ClassLoader { * * // 根據 class全限定名稱 載入Class * public Class<?> loadClass(String name) throws ClassNotFoundException {} * } * */
/** * 【JVM-類載入子系統-雙親委派機制】 * JVM 對 class檔案 採用的是 按需載入(使用該類時,再進行載入); * 載入 某個class檔案時,採用 雙親委派機制 (把 載入請求 交由 上級載入器 載入); * 如果 上級 類載入器 不能完成 類的載入,才由 本級類載入器 去載入; * * 優勢: * 避免類的重複載入; * 保護程式安全,防止 核心 API 被篡改; * eg: * 自定義 java.lang.String類... */
/** * 【JVM-類載入子系統-其他】 * 在同一個JVM中,表示2個class物件是否一致的必要條件: 類全限定名 + ClassLoader * a, 類的全限定名稱相同 * b, 載入該類的ClassLoader相同 */