Java 類載入ClassLoader學習心得

來源:互聯網
上載者:User

標籤:public   fine   網路   server   初始   cep   nat   目錄   心得   

本文是筆者在學習Java 類載入的過程中,整理的心得體會,共勉!

類載入的意義

簡單概念:

將Java類的.class檔案中的位元據讀入到記憶體中,放置在運行時資料區的方法區內。

什麼時候會進行類載入?

         本地系統載入;

         代理載入,比如Spring的AOP動態代理;

         從jar包中載入;

         等等等等

ClassLoader類結構介紹

ClassLoader是一個抽象類別,核心方法如下:

defineClass():目的是將byte位元組流解析成JVM能夠識別的Class對象。

findClass():此方法支援重載,與defineClass()配合使用,目的是擷取Class對象的位元組碼。這個方法的意義在於,我們不僅僅可以通過class檔案執行個體化對象,也可以通過其他方式,比如從網路上擷取的位元組碼檔案,可能會有對應的加密規則。

loadClass():此方法支援重載,目的是擷取載入類的類對象。

resolveClass():實現讓JVM連結這個類,此方法調用的是本地方法,不能重載。

Class類的生命週期

 

 

此生命週期對應到ClassLoader類的具體方法:
載入:loadClass()、findClass()、defineClass()

串連:包括驗證、準備、解析:resolveClass() 本地native方法

初始化:JVM負責

類載入機制(雙親委託)

概念介紹:

大致的ClassLoader分類:

  1. Bootstrap ClassLoader:負責載入存放在JDK\jre\lib(JDK代表JDK的安裝目錄,下同)下,或被 -Xbootclasspath參數指定的路徑中的,並且能被虛擬機器識別的類庫
  2. ExtClassLoader:負責載入JDK\jre\lib\ext目錄中,或者由 java.ext.dirs系統變數指定的路徑中的所有類庫(如javax.開頭的類),開發人員可以直接使用擴充類載入器
  3. AppClassLoader:負責載入使用者類路徑(ClassPath)所指定的類,其父類是ExtClassLoader

心得體會:

  這裡的父載入器與子載入器 在java類別關係上並不是繼承關係;

  實現自己的類載入器,不管是直接實現抽象類別ClassLoader,還是繼承其他子類,父載入器都是AppClassLoader;

類載入的方式

1、命令列啟動應用時候由JVM初始化載入

2、通過Class.forName()方法動態載入

3、通過ClassLoader.loadClass()方法動態載入

Class.forName()ClassLoader.loadClass()區別

Class.forName():將類的.class檔案載入到jvm中之外,還會對類進行解釋,執行類中的static塊;

ClassLoader.loadClass():只幹一件事情,就是將.class檔案載入到jvm中,不會執行static中的內容,只有在newInstance才會去執行static塊。

Class.forName(name,initialize,loader)帶參函數也可控制是否載入static塊。並且只有調用了newInstance()方法採用調用建構函式,建立類的對象 

應用實踐實現自訂的ClassLoader

基於上面對於類載入器的分析,自訂ClassLoader的情況如下:

  1. 需要在自訂路徑下尋找自訂的class檔案
  2. 對我們想要載入的類做特殊處理,比如通過網路傳輸的類的位元組碼可能進行了加密,擷取這種類的位元組碼需要在我們自訂的ClassLoader中實現
  3. 實作類別的熱部署

從上面的分析我們還可以得到,自訂ClassLoader的實現思路可以通過繼承ClassLoader類,重寫findClass()來實現,當然你也可以重寫loadClass(),但是預設的loadClass()是實作類別載入雙親委託模式的,除非你想要破壞這種雙親委託模式,不然就別重寫了。

下面是我在本機寫的測試自訂ClassLoader的Demo:

/** * 自訂路徑下的class檔案載入 * @Auther: [email protected] * @Date: 2018/5/31 19:34 * @Description: */public class PathClassLoader extends ClassLoader {    private String classPath;    public PathClassLoader(String classPath) {        this.classPath = classPath;    }    private String packageName = "com.trey.classloader.Test";    protected Class<?> findClass(String name) throws ClassNotFoundException {        if(packageName.startsWith(name)) {            byte[] classData = getData(name);            if(classData == null) {                throw new ClassNotFoundException();            } else {                System.out.println("當前類載入器:"+this.getClass().getClassLoader().toString());                return defineClass(name, classData, 0, classData.length);            }        } else {            return super.loadClass(name);        }    }    private byte[] getData(String name) {        String path = classPath + File.separatorChar + name.replace(‘.‘,File.separatorChar) + ".class";        try {            InputStream is = new FileInputStream(path);            ByteArrayOutputStream stream = new ByteArrayOutputStream();            byte[] buffer = new byte[2048];            int num = 0;            while ((num = is.read(buffer)) != -1) {                stream.write(buffer, 0, num);            }            return stream.toByteArray();        } catch (IOException e) {            e.printStackTrace();        }        return null;    }}

 

實作類別的熱部署

這是給自己布置的對類載入學習的總結練習。下面說下自己準備實現的思路:

  1. 實現一個server服務,監聽具體目錄下的所有class檔案的更新情況
  2. 當出現class檔案更新時,使用自訂的classLoader進行載入

 

Java 類載入ClassLoader學習心得

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.