讀《深入理解Java虛擬機》有感——第二部分:虛擬機類載入機制

来源:http://www.cnblogs.com/crazyYouth/archive/2016/04/16/5397781.html
-Advertisement-
Play Games

一、類載入過程 執行時機:編譯程式——>執行程式(JVM啟動、程式運行),類載入發生在程式運行期間 各個階段:分為載入階段、連接階段(驗證、準備、解析)、初始化、使用、卸載 執行順序:大體是按以上階段依次執行,但相互間有交叉 載入——>驗證(文件格式)——>繼續載入——>解析——>驗證(元數據、位元組 ...


一、類載入過程       執行時機:編譯程式——>執行程式(JVM啟動、程式運行),類載入發生在程式運行期間
      各個階段:分為載入階段、連接階段(驗證、準備、解析)、初始化、使用、卸載
      執行順序:大體是按以上階段依次執行,但相互間有交叉                        載入——>驗證(文件格式)——>繼續載入——>解析——>驗證(元數據、位元組碼)——>準備——>初始化
      參與角色:Class文件、Java虛擬機、類載入器                          /**HotSpot的Bootstrap ClassLoader(啟動類載入器)是位於虛擬機內部(由C++實現),其它類載入器外置於JVM(由Java實現)*/   二、說明—各個階段       載入階段:            普通類/介面、 數組類(組件類型為基本類型,如int[][]):獲取、轉化、創建、觸發                    獲取——類載入器載入Class文件(指定路徑+文件名 ——>確定“全限定名稱”——>拿到Class文件(與平臺無關的二進位位元組流))                    轉化——位元組碼以一定轉化成格式,存放在方法區                    創建——方法區中生成一個代表這個類的java.lang.Class對象                    觸發——載入的同時,會觸發父類、關聯引用類的載入                                              class A extends B————>Class<B>                                private Class<Person> class————>Class<Person>                                 Class c =Person.getClass(); ————>Class<Person>                                                                     
1.關於“類載入器”和“生成的這個Class對象”:
1)類載入器
Bootstrap Loader(啟動類載入器)、Extended Loader(標準擴展類載入器ExtClassLoader)、AppClass Loader(系統類載入器/應用程式類載入器AppClassLoader)
啟動類載入器:
目的:載入java_home\lib目錄下的位元組碼文件(如:rt.jar,含有java.lang.Object等基本類) 具體有哪些文件及載入順序?
方式:載入System.getProperty("sun.boot.class.path")所指定的路徑或jar,在使用Java運行程式時,也可以指定其搜索路徑,例如:java -Djava.ext.dirs=d:\projects\testproj\classes HelloWorld 參考:http://www.cnblogs.com/ITtangtang/p/3978102.htm
               標準擴展類載入器:
目的:
載入java_home\lib\ext目錄下的位元組碼文件
                         方式:載入System.getProperty("java.ext.dirs")所指定的路徑或jar。在使用Java運行程式時,也可以指定其搜索路徑,例如:java -Djava.ext.dirs=d:\projects\testproj\classes HelloWorld
結果:<實現類>sun.misc.Luncher@ExtClassLoader————————<繼承關係>ClassLoader>URLClassLoader>AppClassLoader


               應用程式類載入器:
方式:載入System.getProperty("java.class.path")所指定的路徑或jar。在使用Java運行程式時,也可以加上-cp來覆蓋原有的Classpath設置,例如: java -cp ./lavasoft/classesHelloWorld
結果:<實現類>sun.misc.Luncher@AppClassLoader————————<繼承關係>ClassLoader>URLClassLoader>AppClassLoader

自定義類載入器:
方式:1)繼承java.lang.ClassLoader並重寫loadClass方法;2)繼承java.lang.ClassLoader並重寫findClass方法/**JDK1.2後推薦,原因見下方紅色部分*/
相關:
 1 <一>java.lang.Object
 2 1.getClass()
 3 public final native Class<?> getClass();    //拿到運行時的Class對象【通過本地方法】
 4 /**
 5  *例子:class-Test>main> 
 6  *                    Class c =Person.getClass();
 7  */
 8      /**
 9        *實現:  
10        *1)虛擬機啟動
11        *2)虛擬機類載入——Test.class————載入階段:方法區>外部介面>new java.lang.Class  //Class<?>     
12        *3)虛擬機類載入——java.lang.Object————【Test載入階段】觸發
13        *3)虛擬機類載入——Person.class    ————【Test載入階段】觸發
14        *4)應用程式啟動
15        *5)調用java.lang.ClassLoader>xxx1()、xxx2().....——返回運行時<Person>Class對象
16        */
17 
18 
19 <二>java。lang.ClassLoader
20       1.loadClass(String name, boolean resolve)  /**載入指定名稱(包括包名)的二進位類型,同時指定是否解析*/
21         loadClass(String name)   
22     protected Class<?> findClass(String name) throws ClassNotFoundException {   //空方法
23         throw new ClassNotFoundException(name);
24     }
25     protected Class<?> loadClass(String name, boolean resolve)    //拿到類載入器【通過本地方法】
26         throws ClassNotFoundException
27     {
28         synchronized (getClassLoadingLock(name)) {
29             // First, check if the class has already been loaded
30             Class c = findLoadedClass(name);
31             if (c == null) {
32                 long t0 = System.nanoTime();
33                 try {
34                     if (parent != null) {
35                         c = parent.loadClass(name, false);
36                     } else {
37                         c = findBootstrapClassOrNull(name);
38                     }
39                 } catch (ClassNotFoundException e) {
40                     // ClassNotFoundException thrown if class not found
41                     // from the non-null parent class loader
42                 }
43 
44                 if (c == null) {
45                     // If still not found, then invoke findClass in order
46                     // to find the class.
47                     long t1 = System.nanoTime();
48                     c = findClass(name);
49 
50                     // this is the defining class loader; record the stats
51                     sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
52                     sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
53                     sun.misc.PerfCounter.getFindClasses().increment();
54                 }
55             }
56             if (resolve) {
57                 resolveClass(c);
58             }
59             return c;
60         }
61     }
62     
63     
64     
65     
66 <三>java.lang.Class   
67      1.getClassLoader()
68 /**例子:class-Test>main>
69   *                    Object o =new Object();
70   *                       System.out.println(o.getClass().getClassLoader());
71                                                                    結果>java.lang.NullPointerException   
72   */                          
73      /**
74       *Returns the class loader for the class.  
75       *This method will return null in such implementations if this class was loaded by the bootstrap class loader. 
76       *如果沒有指定classLoader就預設返回bootstrap classLoader(啟動類載入器),因為這個bootstrap classLoader
77       *用戶拿不到實例,所以返回null表示返回的是bootstrap classLoader     
78       */
79 native ClassLoader getClassLoader0();      //拿到類載入器【通過本地方法】
80 public ClassLoader getClassLoader() {
81         ClassLoader cl = getClassLoader0();
82         if (cl == null)
83             return null;
84         SecurityManager sm = System.getSecurityManager();
85         if (sm != null) {
86             ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass());
87         }
88         return cl;
89     }
2.指定類載入器載入類
Class.forName(name, initialize, loader)

 

       2)與“生成的Class對象”關係
同一Class文件只有被同一類載入器載入,才能判斷為相等————>相等的意義在於:1)不相等,會生成多個Class對象;相等,只會生成一個Class對象
2) 只有同一個Class對象,
equals()、isAssignabaleFrom()、instanceof、isInstance()返回結果才相同;
       3)雙親委派模型 

關係?
上一級持有下一級的一個引用,屬於 has A關係
分工?(為什麼叫雙親委派)
一個類載入器收到了類載入的請求,它首先不會自己去嘗試載入這個類,而是把這個請求委派給上一層的類載入器去完成。只有當上級載入器在搜索範圍找不到所需類,無法完成這個載入請求時,下級載入器才會嘗試自己去載入
好處?
Java類隨著它的類載入器一起具備了一種優先順序的層次關係



2.載入“類/介面”的策略:
非數組類/介面、數組類(組件類型為基本類型,如int[][]):
載入生成代表這個類的java.lang.Class對象後,將在類載入器的“類名稱空間”上標識為“已載入”(因為前面已經討論了,
同一Class文件對應同一個類載入器才確定生成的是同一個Class對象)
           數組類(組件類型為引用類型,如Person[][])、非數組類/介面:                  遞歸載入組件類型,每次去掉一個維度


 

      連接階段

            驗證——文件格式、元數據、位元組碼

            準備——在方法區為類變數分配記憶體並初始化

                               例子                     編譯時期                                                             (類載入時)驗證階段—準備時期

                static int i =20;             產生constantValue屬性,但不會存入常量20                       常規方式進行準備:初始化、分配記憶體

                             結果—————>        無                                                                                    0                                                                                            

         final static int i =20;             產生constantValue屬性,並存20到constantValue               從對應constantValue取出來初始化

                             結果—————>       20                                                                                   20

            解析——將運行時常量池的符號引用替換為直接引用(指向記憶體目標的句柄),這一過程又叫“靜態綁定/靜態連接”

 

 

 

      初始化階段:(動態綁定/動態連接)               1. 執行時機——主動引用(new、反射、父類、執行主類包含main方法、調用靜態方法                   *new                            ——執行父類的<clinit>()、執行本類的<clinit>()、執行父類的<client>、執行本類的<client>
 1 //例子(筆試常考題目)
 2 public class Father {
 3 
 4 private static int i =20;
 5 static{
 6     System.out.println("Father;(類構造器-before)"+i);
 7     i =50;
 8     System.out.println("Father;(類構造器-after)"+i);
 9 }
10 public Father() {
11     System.out.println("Father:(實例構造器)"+i);13 }
14 
15 }
16 
17 
18 
19 public class Son extends Father{
20 
21     private static int i =20;
22     static{
23         System.out.println("Son;(類構造器-before)"+i);
24         i =50;
25         System.out.println("Son;(類構造器-after)"+i);
26     }
27     public Son() {
28         System.out.println("Son:(實例構造器)"+i);        30     }
31 }
32 
33 
34 
35 public class Main {
36 
37     public static void main(String[] args) {
38         new Son();
39 
40     }
41 
42 }
43 
44 //輸出結果:
45         /**
46            *Father;(類構造器-before)20
47            *Father;(類構造器-after)50
48            *Son;(類構造器-before)20
49            *Son;(類構造器-after)50
50            *Father:(實例構造器)50
51            *Son:(實例構造器)50
52            */

 

                   2.主動引用、被動引用                              被動引用——會發生類載入,但不會初始化                                          ——例子:略
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 首先配置好xdebug 在php.ini裡面加入以下配置(修改完註意重啟apache或nginx): [xdebug] zend_extension="/usr/local/opt/php55-xdebug/xdebug.so" xdebug.remote_enable=On xdebug.remo ...
  • JetBrains PhpStorm 8註冊碼一枚 進入:C:\Users\Bruce\.WebIde80\config\colors,把附件放入該文件夾內(點擊下載) 註:如果是mac系統,則放入:/Users/bruce/Library/Preferences/WebIde80/colors目錄 ...
  • 首先,先看一下java中對ArrayList的定義代碼: 這段代碼能給我們提供的信息: 第一:ArrayList實現了RandomAccess介面,因此查詢會很快 第二:ArrayList實現了序列化和Cloneable介面,講道理應該可以進行克隆操作,但是這裡有爭議說不是,因為這樣操作是同一個對象 ...
  • 博主昨天優化了介面框架想著再添加些功能 想到對介面的性能壓力測試 在工作過程中之前都是使用的工具 如:loadrunner、jmeter 想著這次準備用python實現對介面的性能壓力測試 首先要實現這個功能就要運用到python的threading模塊 下麵是自己學習摸索出來的代碼: 這個是10個 ...
  • (String)、Object.toString()正常情況下跟String.valueOf()沒有區別。 但當Object是null的時候。toString會拋出異常、valueOf返回"null",而(String)返回null。 ...
  • Problem A: STL——靈活的線性表 Problem A: STL——靈活的線性表 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 2986 Solved: 1092[Submit][Status][Web Board] Description 數 ...
  • PriorityQueue是隊列的一種,它叫做優先隊列,該類實現了Queue介面。 之所以叫做優先隊列,是因為PriorityQueue實現了Comparator這個比較介面,也就是PriorityQueue內部具有了排序方法,在offer(插入)或poll(彈出)元素的過程中,優先隊列中的數據會動 ...
  • Reverse digits of an integer. Example1: x = 123, return 321Example2: x = -123, return -321 代碼如下: public class Solution { public int reverse(int n) { l ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...