JVM類加載器子系統

類加載器子系統作用

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Ro2NHDU9-1593233589146)(C:\Users\Shinelon\AppData\Roaming\Typora\typora-user-images\image-20200626193122314.png)]

  • 類加載器子系統負責從文件系統或者網絡中加載class文件,class文件在文件開頭有特點的文件標識
  • ClassLoader只負責class文件的加載,至於它是否可以運行,則有Execution Engine決定
  • 加載的類信息存放於一塊稱爲方法區的內存空間,除了類的信息外,方法區中還會存放運行時常量池信息,可能還包括字符串字面量和數字常量

類的加載過程

加載
  • 通過一個類的全限定名獲取此類的二進制字節流
  • 將這個字節流所代表的靜態存儲結構轉化爲方法區的運行時數據結構
  • 在內存中生成一個代表這個類的java.lang.Class對象。作爲方法區這個類的各種數據的訪問入口
鏈接
1.驗證
  • 目的在於確保class文件的字節流中包含信息符合當前虛擬機要求,保證被加載類的正確性,不會危害虛擬機自身安全
  • 主要包括四種驗證:文件格式驗證,元數據驗證,字節碼驗證,符號 引用驗證

2.準備

  • 爲類變量分配內存並且設置該類變量的默認初始值,即零值
  • 這裏不包含用final修飾的static,因爲final在編譯的時候就會分配了,準備階段會顯式初始化
  • 這裏不會爲實例變量分配初始化,類變量會分配在方法區中,而實例變量是會隨着對象一起分配到java堆中

3.解析

  • 將常量池內的符號引用轉換爲直接引用的過程
  • 解析會伴隨着jvm在執行完初始化之後再執行
  • 符號引用就是一組符號來描述所引用的目標。符號引用的字面量形式明確定義在《java虛擬機規範》的class文件格式中,直接引用就是直接指向目標的指針,相對偏移量或一個簡潔定位到目標的句柄
  • 解析動作主要針對類或接口,字段,類方法,接口方法,方法類型等,對應常量池中的CONSTANT_CLASS_info,CONSTANT_Fieldref_info,CONSTANT_Methodref_info等
初始化
  • 初始化階段就是執行類 構造器方法 ()的過程。
  • 此方法不需定義,是javac編譯 器自動收集類中的所有類變量的賦值動作和靜態代碼塊中的語句合併而來。
  • 構造器方法中指令按語句在源文件中出現的順序執行。
  • ()不同於類的構造器。(關聯:構造器是虛擬機視角下的())
  • 若該類具有父類,JVM會 保證子類的()執行前,父類的()已經執行完畢。
  • 虛擬機必須保證一個類的()方法在多線程下被同步加鎖。

類加載器的分類

  • JVM支持兩種類型的類加載器,分別爲引導類加載器( BootstrapClassLoader)和自定義類加載器(Usler-Defined ClassLoader) 。
  • 從概念,上來講,自定義類加載器一般指的是程序中由開發人員自定義的一類類加載器,但是Java虛擬機規範卻沒有這麼定義,而是將所有派生於抽象類ClassLoader的類加載器都劃分爲自定義類加載器。
  • 無論類加載器的類型如何劃分,在程序中我們最常見的類加載器始終只有3個,如下所示:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-wEC2hhrt-1593233589173)(C:\Users\Shinelon\AppData\Roaming\Typora\typora-user-images\image-20200626213914624.png)]

啓動類加載器(引導類加載器,Bootstrap ClassLoader)
  • 這個類加載使用C/C++語言實現的,嵌套在JVM內部。
  • 它用來加載Java的核心庫(JAVA_ HOME/j re/ lib/rt. jar、esources. jar或sun. boot. class.path路徑下的內容) ,用於提供JVM自身需要的類
  • 並不繼承自java. lang . ClassLoader,沒有父加載器。
  • 加載擴展類和應用程序類加載器,並指定爲他們的父類加載器。
  • 出於安全考慮,Bootstrap啓動類加載器只加載包名爲java、javax、sun等開頭的類
擴展類加載器(Extension ClassLoader)
  • Java語言編寫,由sun. misc . Launcher$ExtClassLoader實現。
  • 派生於ClassLoader類
  • 父類加載器爲啓動類加載器
  • 從java. ext.di rs系統屬性所指定的目錄中加載類庫,或從JDK的安裝目錄的jre/lib/ext子目錄(擴展目錄)下加載類庫。如果用戶創建的JAR放在此目錄下,也會自動由擴展類加載器加載。
應用程序類加載器(系統類加載器,AppclassLoader)
  • java語 言編寫,由sun.misc. Launcher $AppClassLoader實現
  • 派生於ClassLoader類
  • 父類加載器爲擴展類加載器
  • 它負責加載環境變量classpath或系統屬性java.class.path 指定路徑下的類庫
  • 該類加載是程序中默認的類加載器,一般來說,Java應用的類都是由它來完成加載
  • 通過ClassLoader #getSystemClassLoader()方法可以獲取到該類加載器
用戶自定義類加載器
  • 在Java的日常應用程序開發中,類的加載幾乎是由,上述3種類加載器相互配合執行的,在必要時,我們還可以自定義類加載器,來定製類的加載方式。

爲什麼要自定義類加載器?

  • 隔離加載類
  • 修改類加載的方式
  • 擴展加載源
  • 防止源碼泄漏

用戶自定義類加載器實現步驟

  • 開發人員可以通過繼承抽象類java. lang. ClassLoader類的方式, 實現自己的類加載器,以滿足一些特殊的需求
  • 在JDK1.2之前, 在自定義類加載器時,總會去繼承ClassLoader類並重寫loadClass ()方法,從而實現自定義的類加載類,但是在JDK1.2之後已不再建議用戶去覆蓋loadClass()方法,而是建議把自定義的類加載邏輯寫在findClass()方法中
  • 在編寫自定義類加載器時,如果沒有太過於複雜的需求,可以直接繼承URLClassLoader類,這樣就可以避免自己去編寫findClass()方法及其獲取字節碼流的方式,使自定義類加載器編寫更加簡潔。

雙親委派機制

基本介紹:Java虛擬機對class文件採用的是按需加載的方式,也就是說當需要使用該類時纔會將它的class文件加載到內存生成class對象。而且加載某個類的class文件時,Java虛擬機採用的是雙親委派機制,即把請求交由父類處理,它是一種任務委派模式。

工作原理

  • 如果一個類加載器收到了類加載請求,它並不會自己先去加載,而是把這個請求委託給父類的加載器去執行
  • 如果父類加載器還存在其父類加載器,則進一步向上委託,依次遞歸,請求最終將到達頂層的啓動類加載器
  • 如果父類加載器可以完成類加載任務,就成功返回,倘若父類加載器無法完成加載任務,子加載器纔會嘗試自己去加載,這就是雙親委派模式

優勢

  • 避免類的重複加載
  • 保護程序的安全,防止核心API被隨意篡改

沙箱安全機制

自定義String類,但是在加載自定義String類的時候會率先使用引導類加載器加載,而引導類加載器在加載的過程中會先加載jdk自帶的文件(rt. jar包中java\lang\String. class),報錯信息說沒有main方法,就是因爲加載的是rt. jar包中的String類。這樣可以保證對java核心源代碼的保護,這就是沙箱安全機制。

其他

  • 在JVM中表示兩個class對象是否爲同一個類存在兩個必要條件:
    • 類的完整類名必須一致,包括包名
    • 加載這個類的ClassLoader(ClassLoader實例對象)必須相同
  • 在JVM中,即使這兩個類對象來源於同一個class文件,被同一個虛擬機所加載,但只要加載它們的ClassLoader實例對象不同,那麼這兩個類對象也是不相等的
對類的加載器的引用

JVM必須知道一個類型是由啓動加載器加載的還是由用戶類加載器加載的。如果一個類型是由用戶類加載器加載的,那麼JVM會將這個類加載器的一個引用作爲類型信息的一部分保存在方法區中。當解析一個類型到另一個類型的引用的時候,JVM需要保證這兩個類型的加載器是相同的

類的主動使用與被動使用
  • 主動使用,又分爲七種情況:
    • 創建類的實例
    • 訪問某個類或接口的靜態變量,或者對該靜態變量賦值
    • 調用類的靜態方法
    • 反射
    • 初始化一個類的子類
    • Java虛擬機啓動時被標明爲啓動類的類
    • JDK 7開始提供的動態語言支持:java. lang. invoke . MethodHandle實例的解析結果REF getStatic、 REF putStatic、 REF invokeStatic句柄對應的類沒有初始化。
  • 則初始化除了上七種情況,其他使用Java類的方式都被看作是對類的被動使用,都不會導致類的初始化。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章