Java 自定義 ClassLoader 實(shí)現(xiàn) JVM 類加載

定義需要加載的類

為了能夠?qū)崿F(xiàn)類加載,并展示效果,定義一個(gè)Hello類痊夭,再為其定義一個(gè)sayHello()方法,加載Hello類之后脏里,調(diào)用它的sayHello()方法她我。

public class Hello {
    public static void sayHello(){
        System.out.println("Hello,I am ....");
    }
}

定義類加載器

自定義加載器,需要繼承ClassLoader,并重寫里面的protected Class<?> findClass(String name) throws ClassNotFoundException方法。

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;

public class MyClassLoader extends ClassLoader {
    /**
     * 重寫父類方法番舆,返回一個(gè)Class對(duì)象
     * ClassLoader中對(duì)于這個(gè)方法的注釋是:
     * This method should be overridden by class loader implementations
     */
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        Class clazz = null;
        String classFilename = name + ".class";
        File classFile = new File(classFilename);
        if (classFile.exists()) {
            try (FileChannel fileChannel = new FileInputStream(classFile)
                    .getChannel();) {
                MappedByteBuffer mappedByteBuffer = fileChannel
                        .map(MapMode.READ_ONLY, 0, fileChannel.size());
                byte[] b = mappedByteBuffer.array();
                clazz = defineClass(name, b, 0, b.length);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (clazz == null) {
            throw new ClassNotFoundException(name);
        }
        return clazz;
    }
    
    public static void main(String[] args) throws Exception{
        MyClassLoader myClassLoader = new MyClassLoader();
        Class clazz = myClassLoader.loadClass(args[0]);
        Method sayHello = clazz.getMethod("sayHello");
        sayHello.invoke(null, null);
    }
}

編譯需要加載的類文件

類加載的時(shí)候加載的是字節(jié)碼文件酝碳,所以需要預(yù)先把定義的Hello類編譯成字節(jié)友文件。

javac Hello.java

驗(yàn)證字節(jié)碼文件是否編譯成功恨狈,利用二進(jìn)制文件查看器查看我們編譯之后的文件疏哗,樣式如下:

0000000 177312 137272 000000 032000 016000 000012 000006 004416
0000020 007400 010000 000010 005021 011000 011400 000007 003424
0000040 012400 000001 036006 067151 072151 000476 001400 024450
0000060 000526 002000 067503 062544 000001 046017 067151 047145
0000100 066565 062542 052162 061141 062554 000001 071410 074541
0000120 062510 066154 000557 005000 067523 071165 062543 064506
0000140 062554 000001 044012 066145 067554 065056 073141 006141
0000160 003400 004000 000007 006026 013400 014000 000001 044017
0000200 066145 067554 044454 060440 020155 027056 027056 000007
0000220 006031 015000 015400 000001 044005 066145 067554 000001
0000240 065020 073141 027541 060554 063556 047457 065142 061545
0000260 000564 010000 060552 060566 066057 067141 027547 074523
0000300 072163 066545 000001 067403 072165 000001 046025 060552
0000320 060566 064457 027557 071120 067151 051564 071164 060545
0000340 035555 000001 065023 073141 027541 067551 050057 064562
0000360 072156 072123 062562 066541 000001 070007 064562 072156
0000400 067154 000001 024025 065114 073141 027541 060554 063556
0000420 051457 071164 067151 035547 053051 020400 002400 003000
0000440 000000 000000 001000 000400 003400 004000 000400 004400
0000460 000000 016400 000400 000400 000000 002400 133452 000400
0000500 000261 000000 000001 000012 000000 000006 000001 000000
0000520 000002 000011 000013 000010 000001 000011 000000 000045
0000540 000002 000000 000000 131011 001000 001422 000266 130404
0000560 000000 000400 005000 000000 005000 001000 000000 002000
0000600 004000 002400 000400 006000 000000 001000 006400
0000616

編譯自定義的類加載器并支行程序

?編譯代碼
javac MyClassLoader.java
?當(dāng)然我們也可以同時(shí)編譯我們所有的java源文件
javac *.java

執(zhí)行成功之后,我們用下面的語(yǔ)句執(zhí)行代碼禾怠,測(cè)試是否成功返奉,并查看結(jié)果

java MyClassLoader Hello
?運(yùn)行結(jié)果
Hello,I am ....

當(dāng)程序按照預(yù)期顯示,就證明我自定義類加載器成功了吗氏。

總結(jié)

通過上面的程序代碼芽偏,簡(jiǎn)單的實(shí)現(xiàn)JVM的類加載過程,知道了程序運(yùn)行的一點(diǎn)流程弦讽。但是在編寫的時(shí)候有如下坑需要注意

  • 類文件不需要指定包污尉,否則加載的時(shí)候我們需要額外的處理,把包中的"."替換成文件系統(tǒng)的路徑"/"往产。
  • 需要加載的Hello類中的反射調(diào)用的方法要用static修飾十厢,這樣invoke的時(shí)候第一個(gè)參數(shù)才可以使用null關(guān)鍵字代替,否則需要?jiǎng)?chuàng)建一個(gè)對(duì)應(yīng)的類實(shí)例捂齐。
    官方文檔中有這樣一句話<blockquote>If the underlying method is static, then the specified obj argument is ignored. It may be null.</blockquote>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市缩抡,隨后出現(xiàn)的幾起案子奠宜,更是在濱河造成了極大的恐慌,老刑警劉巖瞻想,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件压真,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡蘑险,警方通過查閱死者的電腦和手機(jī)滴肿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)佃迄,“玉大人泼差,你說我怎么就攤上這事『乔危” “怎么了堆缘?”我有些...
    開封第一講書人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)普碎。 經(jīng)常有香客問我吼肥,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任缀皱,我火速辦了婚禮斗这,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘啤斗。我一直安慰自己表箭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開白布争占。 她就那樣靜靜地躺著燃逻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪臂痕。 梳的紋絲不亂的頭發(fā)上伯襟,一...
    開封第一講書人閱讀 51,258評(píng)論 1 300
  • 那天,我揣著相機(jī)與錄音握童,去河邊找鬼姆怪。 笑死,一個(gè)胖子當(dāng)著我的面吹牛澡绩,可吹牛的內(nèi)容都是我干的稽揭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼肥卡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼溪掀!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起步鉴,我...
    開封第一講書人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤揪胃,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后氛琢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體喊递,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年阳似,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了绝淡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屋确。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡踱启,死狀恐怖弯菊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情畜吊,我是刑警寧澤藐石,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站定拟,受9級(jí)特大地震影響于微,放射性物質(zhì)發(fā)生泄漏逗嫡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一株依、第九天 我趴在偏房一處隱蔽的房頂上張望驱证。 院中可真熱鬧,春花似錦恋腕、人聲如沸抹锄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)伙单。三九已至,卻和暖如春哈肖,著一層夾襖步出監(jiān)牢的瞬間吻育,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工淤井, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留布疼,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓币狠,卻偏偏與公主長(zhǎng)得像游两,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子漩绵,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理贱案,服務(wù)發(fā)現(xiàn),斷路器止吐,智...
    卡卡羅2017閱讀 134,654評(píng)論 18 139
  • 一祟印、JVM內(nèi)幕:Java虛擬機(jī)詳解(java se 7規(guī)范) 直接上圖,再逐步解釋粟害。 上圖顯示的組件分兩個(gè)章節(jié)解釋...
    屈小勇閱讀 1,846評(píng)論 6 22
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法蕴忆,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法悲幅,繼承相關(guān)的語(yǔ)法套鹅,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚_t_閱讀 31,625評(píng)論 18 399
  • JVM類加載機(jī)制 概述 類加載過程 加載 通過類的全限定名獲取類的二進(jìn)制流 將靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)...
    東溪95閱讀 3,033評(píng)論 0 15
  • 這篇文章解釋了Java 虛擬機(jī)(JVM)的內(nèi)部架構(gòu)汰具。下圖顯示了遵守Java SE 7 規(guī)范的典型的 JVM 核心內(nèi)...
    飲墨饗書閱讀 659評(píng)論 0 1