自定義類加載器

// 待類加載的類
package com.infuq;
public class Ticket { }

自定義類加載器 MyClassLoader

package com.infuq;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

/**
 * 自定義類加載器
 *
 * 加載指定路徑scanPath下的類文件
 *
 */
public class MyClassLoader extends ClassLoader {

    // MyClassLoader可以掃描的路徑. 例如: /usr/include
    private final String scanPath ;


    public MyClassLoader(String scanPath){
        super();
        this.scanPath = scanPath;
    }


    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {

        byte[] classData = readFileData(name);

        if (classData != null) {
            return this.defineClass(name, classData, 0, classData.length);
        }

        return null;
    }


    // 讀取clazzName對應(yīng)的文件內(nèi)容, 返回字節(jié)數(shù)組
    private byte[] readFileData(String clazzName) {

        File file;

        /*
         * 假如scanPath=/usr/include
         * 由于入?yún)lazzName是類的全限定名, 例如java.lang.Object
         * 為了讀取clazzName對應(yīng)的文件, 需要將字符串`java.lang.Object`轉(zhuǎn)成`java/lang/Object`
         * 最后得到完整文件路徑/usr/include/java/lang/Object.class
         */
        if (System.getProperty("os.name").contains("Windows")) {
            clazzName = clazzName.replace(".", "\\");
            file = new File(scanPath + "\\" + clazzName + ".class");
        }
        else {
            clazzName = clazzName.replace(".", "/");
            file = new File(scanPath + "/" + clazzName + ".class");
        }


        // 讀取
        if (file.exists()) {
            FileInputStream in = null;
            ByteArrayOutputStream out;
            try {
                in = new FileInputStream(file);
                out = new ByteArrayOutputStream();

                byte[] buffer = new byte[1024];
                int size;
                while ((size = in.read(buffer)) != -1) {
                    out.write(buffer, 0, size);
                }

                return out.toByteArray();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (in != null) {
                        in.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return null;

    }
}

測試類 Example


package com.infuq;

import java.util.Scanner;

public class Example {

    public static void main(String[] args) throws Exception {

        System.out.print("請輸入類加載的路徑: ");
        Scanner scanner = new Scanner(System.in);

        /*
         * 從命令行讀取指定掃描的路徑
         * 例如
         * Unix : /usr/bin/
         * Windows : D:\\repository\\class
         */
        String scanPath = scanner.next();
        MyClassLoader myClassLoader = new MyClassLoader(scanPath);

        /*
         * 讀取類的全限定名, 例如 java.lang.Object
         *
         */
        System.out.print("請輸入待加載的類全限定名稱: ");
        String packageNamePath = scanner.next();


        System.out.println();
        Class<?> clazz = myClassLoader.loadClass(packageNamePath);
        if (clazz != null)
            System.out.println(packageNamePath + "類加載器是: " + clazz.getClassLoader());
        
        System.out.println("系統(tǒng)類加載器掃描文件路徑: " + System.getProperty("java.class.path"));

    }

}

編譯 Ticket.java , MyClassLoader.java , Example.java 三個(gè)源文件, 文件結(jié)構(gòu)圖如下

文件結(jié)構(gòu)圖

以上源文件在 /Users/infuq/Repository/GitLab/infuq-others/Lab/2022-3-22 目錄下

其中還把待加載的Ticket.class文件拷貝一份到了自定義的JAVA-INF目錄下, 后面會(huì)用到

【測試一】

image.png

本計(jì)劃讓自定義類加載器MyClassLoader 加載/Users/infuq/Repository/GitLab/infuq-others/Lab/2022-3-22/JAVA-INF目錄下的com.infuq.Ticket類, 根據(jù)雙親委派, 委派給了系統(tǒng)類加載器. 而當(dāng)前目錄下就有一個(gè)com.infuq.Ticket類, 因此這個(gè)Ticket類被系統(tǒng)類加載器加載了.

改個(gè)名稱, 故意讓系統(tǒng)類加載器找不到Ticket類


image.png

繼續(xù)上面的相同執(zhí)行


image.png

這個(gè)時(shí)候com.infuq.Ticket就被自定義類加載器加載了.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末岗屏,一起剝皮案震驚了整個(gè)濱河市辆琅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌这刷,老刑警劉巖婉烟,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異暇屋,居然都是意外死亡似袁,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來昙衅,“玉大人扬霜,你說我怎么就攤上這事《妫” “怎么了著瓶?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長婴谱。 經(jīng)常有香客問我蟹但,道長,這世上最難降的妖魔是什么谭羔? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任华糖,我火速辦了婚禮,結(jié)果婚禮上瘟裸,老公的妹妹穿的比我還像新娘客叉。我一直安慰自己,他們只是感情好话告,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布兼搏。 她就那樣靜靜地躺著,像睡著了一般沙郭。 火紅的嫁衣襯著肌膚如雪佛呻。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天病线,我揣著相機(jī)與錄音吓著,去河邊找鬼。 笑死送挑,一個(gè)胖子當(dāng)著我的面吹牛绑莺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播惕耕,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼纺裁,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了司澎?” 一聲冷哼從身側(cè)響起欺缘,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎挤安,沒想到半個(gè)月后浪南,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡漱受,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年络凿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了骡送。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,626評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡絮记,死狀恐怖摔踱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情怨愤,我是刑警寧澤派敷,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站撰洗,受9級特大地震影響篮愉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜差导,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一试躏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧设褐,春花似錦颠蕴、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至外冀,卻和暖如春寡键,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背雪隧。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工西轩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人膀跌。 一個(gè)月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像固灵,于是被迫代替她去往敵國和親捅伤。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評論 2 348

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