1. 程式人生 > 其它 >JVM---類載入子系統

JVM---類載入子系統

 

/**
     *  【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相同
     */