讀《深入理解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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...