java開發兩年,類加載器及其加載過程都搞不明白,那你工做可能不保了!

內存結構概述

內存結構簡圖:
java

內存結構詳細圖:面試

中文:
segmentfault

英文:

在這裏我的整理了一些資料,有須要的朋友能夠直接點擊領取。安全

Java基礎知識大全網絡

22本Java架構師核心書籍數據結構

從0到1Java學習路線和資料架構

1000+道2021年最新面試題工具

類加載器與加載過程

類加載器子系統做用學習

圖解:
url

描述:

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

我的理解:

類加載器ClassLoader做用

圖解:

描述:

  • class file存在於本地硬盤上,能夠理解爲設計師畫在紙上的模板,而最終這個模板在執行的時候是要
    加載到JVM當中來根據這個文件實例化出n個如出一轍的實例。
  • class file 加載到JVM中,被稱爲DNA元數據模板,放在方法區。
  • 在.class文件->_JVM ->最終成爲元數據模板,此過程就要一個運輸工具(類裝載器class Loader),
    扮演一個快遞員的角色。

我的理解:

類加載過程

圖解:

描述:

//加載:
1.經過一個類的全限定名獲取定義此類的二進制字節流
2.將這個字節流所表明的靜態存儲結構轉化爲方法區的運行時數據結構
3.在內存中生成一個表明這個類的java.lang.class對象,做爲方法區這個類的各類數據的訪問入口
//連接:
- 驗證:目的在於確保class文件的字節流中包含信息符合當前虛擬機要求,保證被加載類的正確性,
       不會危害虛擬機自身安全,主要包括四種驗證,文件格式驗證,元數據驗證,字節碼驗證,
       符號引用驗證。
- 準備:爲類變量分配內存而且設置該類變量的默認初始值,即零值;這裏不包含用final修飾的static,
       由於final在編譯的時候就會分配了,準備階段會顯式初始化;這裏不會爲實例變量分配初始化,
       類變量會分配在方法區中,而實例變量是會隨着對象一塊兒分配到Java堆中。
- 解析:將常量池內的符號引用轉換爲直接引用的過程;事實上,解析操做每每會伴隨着JVM在執行完初始化之
        後再執行;符號引用就是一組符號來描述所引用的目標。符號引用的字面量形式明肯定義在《java虛
        擬機規範》的class文件格式中。直接引用就是直接指向目標的指針、相對偏移量或一個間接定位到目
        標的句柄;解析動做主要針對類或接口、字段、類方法、接口方法、方法類型等。對應常量池中的
        CONSTANT Class info、CONSTANT Fieldref info、cONSTANT Methodref info等。
//初始化;

類加載器分類

概述:

JVM支持兩種類型的類加載器,分別爲引導類加載器(BootstrapClassLoader)和自定義類加載器(User-Defined classLoader),從概念上來說,自定義類加載器通常指的是程序中由開發人員自定義的一類類加載器,可是Java虛擬機規範卻沒有這麼定義,而是將全部派生於抽象類ClassLoader的類加載器都劃分爲自定義類加載器。

圖解:

描述:

//虛擬機自帶的類加載器:
啓動類加載器(引導類加載器,Bootstrap classLoader):
1.這個類加載使用c/C++語言實現的,嵌套在JVM內部。
2.它用來加載Java的核心庫(JAVA_HOME/jre/lib/rt.jar、resources.jar或sun.boot.class.path
  路徑下的內容),用於提供JVM自身須要的類;
3.並不繼承自java.lang.ClassLoader,沒有父加載器。
4.加載擴展類和應用程序類加載器,並指定爲他們的父類加載器。
5.出於安全考慮,Bootstrap啓動類加載器只加載包名爲java、 javax、sun等開頭的類

擴展類加載器(Extension ClassLoader):
1.擴展類加載器(Extension ClassLoader)
2.Java語言編寫,由sun.misc.Launciler$ExtClassLoader實現。派生於classLoader類
3.父類加載器爲啓動類加載器
4.從java.ext.dirs系統屬性所指定的目錄中加載類庫,或從JDK的安裝目錄的jre/lib/ext子目錄(擴展
  目錄)下加載類庫。若是用戶建立的JAR放在此目錄下,也會自動由擴展類加載器加載。

應用程序類加載器(系統類加載器,AppClassLoader):
1.java語言編寫,由sun.misc.Launcher$AppclagsLoader
2.實現派生於classLoader類
3.父類加載器爲擴展類加載器
4.它負責加載環境變量classpath或系統屬性java.class.path指定路徑下的類庫
5.該類加載是程序中默認的類加載器,通常來講,Java應用的類都是由它來完成加載
6.經過classLoader#getSystemclassLoader ()方法能夠獲取到該類加載器

//用戶自定義類加載器:
在Java的平常應用程序開發中,類的加載幾乎是由上述3種類加載器相互配合執行的,在必要時,咱們還能夠
自定義類加載器,來定製類的加載方式。
用戶自定義類加載器實現步驟:
用戶自定義類加載器實現步驟:
1.開發人員能夠經過繼承抽象類java.lang.classLoader類的方式,實現本身的類加載器,以知足一些
  特殊的需求
2.在JDK1.2以前,在自定義類加載器時,總會去繼承classLoader類並重寫loadclass ()方法,從而實現
  自定義的類加載類,可是在JDK1.2以後己再也不建議用戶去覆蓋loadclass()方法,而是建議把自定義的類
  加載邏輯寫在findclass ()方法中
3.在編寫自定義類加載器時,若是沒有太過於複雜的需求,能夠直接繼承URLClassLoader類,這樣就能夠
  避免本身去編寫findclass ()方法及其獲取字節碼流的方式,使自定義類加載器編寫更加簡潔。

ClassLoader的使用說明

概述:

ClassLoader類,它是一個抽象類,其後全部的類加載器都繼承自ClassLoader(不包括啓動類加載器)
圖解:


獲取ClassLoader途徑:

  • 方式一:獲取當前類的ClassLoader -> clazz.getClassLoader ()
  • 方式二:獲取當前線程上下文的ClassLoader -> Thread.currentThread ().getContextclassLoader ()
  • 方式三:獲取系統的ClassLoader -> ClassLoader.getsystemClassLoader()
  • 方式四:獲取調用者的ClassLoader -> DriverManager.getCallerclassLoader ()

雙親委派機制

概述:

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

圖解:

描述:

工做原理:
1)若是一個類加載器收到了類加載請求,它並不會本身先去加載,而是把這個請求委託給父類的加載器去執行;
2)若是父類加載器還存在其父類加載器,則進一步向上委託,依次遞歸,請求最終將到達頂層的啓動類加載器;
3)若是父類加載器能夠完成類加載任務,就成功返回,假若父類加載器沒法完成此加載任務,子加載器纔會嘗試
本身去加載,這就是雙親委派模式。
優點:
1.避免類的重複加載
2.保護程序安全,防止核心API被隨意篡改

√自定義類: java.lang.String

其餘

判斷兩個class對象是否爲同一個類:

  • 類的完整類名必須一致,包括包名。
  • 加載這個類的ClassLoader(ClassLoader實例對象)必須一致。

對類加載器的引用:

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

最後

看到這裏以爲文章對你有幫助的話不妨給小編點個贊,感謝支持!

相關文章
相關標籤/搜索