最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中如何自定義一個類加載器

 更新時間:2022年11月19日 09:56:59   作者:盛世如戀  
這篇文章主要介紹了Java中如何自定義一個類加載器,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

如何自定義加載器?

1.創(chuàng)建一個自定義加載器類 繼承 ClassLoader 類

2.重寫 findClass 方法。 主要是實現(xiàn)從那個路徑讀取 jar包或者.class文件,將讀取到的文件用字節(jié)數(shù)組來存儲,然后可以使用父類的 defineClass 來轉(zhuǎn)換成字節(jié)碼。

如果想破壞雙親委派的話,就重寫 loadClass 方法, 否則不用重寫

注意:

1.ClassLoader提供的 protected final Class<?> defineClass(String name, byte[] b, int off, int len) 是用來將字節(jié)數(shù)組轉(zhuǎn)換成字節(jié)碼文件的,傳入?yún)?shù) 是 (類名,字節(jié)數(shù)組數(shù)據(jù),字節(jié)數(shù)組讀取的開始下標,字節(jié)數(shù)組的長度)

示例:讀取某文件的下的某class文件

創(chuàng)建一個名為MyClassLoader的類加載器:

import java.io.*;

public class MyClassLoader extends ClassLoader{
    String path ;
    MyClassLoader(String dir){
        this.path = dir ;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        try {
            this.path = this.path + name +".class";
            File f = new File(path);
            InputStream in = new FileInputStream(f);
            byte [] bys = new byte[  (int)f.length() ];
            int len = 0;
            while( (len = in.read(bys) )!= -1  ){

            }
            // byte[] -> .class
            return defineClass(name,bys,0,bys.length);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return super.findClass(name);
    }
}

測試:

在如下目錄,生成一個Hello.class字節(jié)碼文件

Hello.java:

public class Hello {
    public void sayHello(){
        System.out.println("Hello World!");
    }
}

在這里插入圖片描述

測試類:

import java.lang.reflect.Method;

public class Test {
    public static void main(String[] args) throws Exception {
        MyClassLoader my = new MyClassLoader("D:\\test\\jvmtest\\");
        Class<?> c1 = my.loadClass("Hello");
        Object o = c1.newInstance();
        Method d = c1.getMethod("sayHello",null);
        d.invoke(o);
    }
}

運行測試類:

在這里插入圖片描述

類加載器的使用及自定義類加載器

package com.tech.load.def;
 
/**
 * @author lw
 * @since 2021/12/3
 */
public class UserImpl {
    static {
        System.out.println("UserImpl init ...");
    }
}
package com.tech.load.def;
 
/**
 * @author lw
 * @since 2021/12/3
 */
public class DefLoader {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        //上下文類加載器,默認使用的是 應用程序類加載器
//        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
//        Class<?> c1 = contextClassLoader.loadClass("com.tech.load.def.UserImpl");
//        c1.newInstance(); //classloader.loadClass 不會觸發(fā)初始化,當創(chuàng)建對象時執(zhí)行初始化,執(zhí)行靜態(tài)程序塊內(nèi)容 輸出 "UserImpl init ..."
//        ClassLoader contextClassLoader1 = Thread.currentThread().getContextClassLoader();
//        Class<?> c2 = contextClassLoader1.loadClass("com.tech.load.def.UserImpl");
//        c2.newInstance(); //使用相同的類加載器 加載相同的類名 則加載的是同一個類,c1 c2是同一個類,由于已經(jīng)初始化過 創(chuàng)建對象不再初始化 不再打印  "UserImpl init ..."
//        System.out.println(contextClassLoader==contextClassLoader1); //true 獲取的上下文類加載器是同一個類加載器 
//        System.out.println(c1==c2); // true 同一個類加載器器,加載同名的類,第一次加載時加載的類會緩存到類加載器的緩存,再次加載直接在緩存讀取,兩次加載的是同一個類
        
        //直接獲取類的類加載器 應用程序類加載器
        ClassLoader classLoader = UserImpl.class.getClassLoader();
        ClassLoader classLoader1 = UserImpl.class.getClassLoader();
        System.out.println(classLoader==classLoader1); //true 獲取的是同一個應用程序類加載器
       
        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
        System.out.println(classLoader==contextClassLoader); //true 線程上下文類加載器默認采用的也是應用程序類加載器 與通過類型對象getClassLoader獲取方式相同
 
        Class<?> c1 = Class.forName("com.tech.load.def.UserImpl"); //會觸發(fā)類的初始化
        ClassLoader classLoader2 = c1.getClassLoader();
        System.out.println(classLoader==classLoader2); //true 獲取的是同一個應用程序類加載器
        
    }
}

在應用程序中,默認我們獲取上下文類加載器、類型對象getClassLoader都是采用的同一個應用程序類加載器,類在第一次被加載后會緩存到類加載器的緩存中,由于是同一個類加載器此時同名的類不能被多次加載,且應用程序類加載器只能加載classpath下的類。

如果我們想加載自定義路徑下的類,需要用到自定義類加載器,可以去指定路徑下加載類,且通過創(chuàng)建多個類加載器對象,加載的同名類相互隔離,也就是說同名類可以被多個自定義類加載器對象加載。

編寫自定義類加載器:

  • 繼承ClassLoader;
  • 重寫findClass方法在指定路徑下進行類的加載,得到字節(jié)數(shù)組,然后使用defineClass根據(jù)字節(jié)數(shù)組生成字節(jié)碼文件 也就是class文件;

編寫一個測試類Goods放在D盤下,javac得到class文件

 
/**
 * @author lw
 * @since 2021/12/3
 */
public class Goods {
    static {
        System.out.println("Goods init ...");
    }
}

javac Goods.java

package com.tech.load.def;
 
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
 
/**
 * 自定義類加載器 加載類
 * @author lw
 * @since 2021/12/3
 */
public class DefLoad7 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        MyClassLoader classLoader1 = new MyClassLoader();
        Class<?> c1 = classLoader1.loadClass("Goods");
        Class<?> c2 = classLoader1.loadClass("Goods");
        System.out.println(c1==c2);//true 使用同一個類加載器加載同名類兩次,實際只加載了一次,第二次是在類加載器的緩存加載的 結(jié)果兩次加載的是同一個
        c1.newInstance(); //會初始化
        c2.newInstance(); //不會初始化 
        
        MyClassLoader classLoader2 = new MyClassLoader();
        Class<?> c3 = classLoader2.loadClass("Goods");
        System.out.println(c1==c3); //false 使用不同的類加載器對同一個類進行加載,會得到不同的類型對象
        c3.newInstance(); //會初始化
    }
}
 
//自定義類加載器 加載D盤下的類
class MyClassLoader extends ClassLoader{
    
    //去指定的路徑下加載類
    //name是類名稱
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        String path="D:\\"+name+".class";
        try {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            //將指定路徑下的文件 拷貝到輸出流
            Files.copy(Paths.get(path),os);
            byte[] bytes = os.toByteArray();
            //調(diào)用父類的方法 根據(jù)字節(jié)數(shù)組生成字節(jié)碼文件 也就是class文件
            //bytes -> *.class
 
            return defineClass(name,bytes,0,bytes.length);
        } catch (IOException e) {
            e.printStackTrace();
            throw new ClassNotFoundException("類文件未找到",e);
        }
    }
}

使用自定義加載器,創(chuàng)建多個類加載器對象去加載同一個類,會得到多個類型對象。 

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java實現(xiàn)對對碰小游戲

    java實現(xiàn)對對碰小游戲

    這篇文章主要為大家詳細介紹了java實現(xiàn)對對碰小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • Spring實戰(zhàn)之調(diào)用實例工廠方法創(chuàng)建Bean操作示例

    Spring實戰(zhàn)之調(diào)用實例工廠方法創(chuàng)建Bean操作示例

    這篇文章主要介紹了Spring實戰(zhàn)之調(diào)用實例工廠方法創(chuàng)建Bean操作,結(jié)合實例形式分析了實例工廠方法創(chuàng)建Bean相關(guān)配置、實現(xiàn)方法及操作注意事項,需要的朋友可以參考下
    2019-11-11
  • java實現(xiàn)多層級zip解壓的示例代碼

    java實現(xiàn)多層級zip解壓的示例代碼

    這篇文章主要為大家詳細介紹了java實現(xiàn)多層級zip解壓的相關(guān)知識,文中的示例代碼講解詳細,具有一定的借鑒價值,有需要的小伙伴可以參考一下
    2024-12-12
  • Java版學生管理系統(tǒng)

    Java版學生管理系統(tǒng)

    這篇文章主要為大家詳細介紹了Java版學生管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • Maven打包SpringBoot工程的實現(xiàn)示例

    Maven打包SpringBoot工程的實現(xiàn)示例

    在使用Spring Boot和Maven的項目中,你可以使用Maven來打包你的項目,本文主要介紹了Maven打包SpringBoot工程的實現(xiàn)示例,具有一定的參考價值,感興趣的可以了解一下
    2024-05-05
  • 在 Spring Boot 3 中接入生成式 AI的操作方法

    在 Spring Boot 3 中接入生成式 AI的操作方法

    本文介紹了如何在SpringBoot3中集成生成式AI,以O(shè)penAI的GPT模型為例,通過代碼示例展示了如何實現(xiàn),SpringBoot3的優(yōu)勢和OpenAI的生成式AI技術(shù)結(jié)合,為開發(fā)者提供了高效集成生成式AI的方法,感興趣的朋友跟隨小編一起看看吧
    2025-01-01
  • Java線程的控制詳解

    Java線程的控制詳解

    這篇文章主要介紹了Java中的join線程、后臺線程、線程睡眠、線程讓步以及線程的優(yōu)先級,非常的詳細,希望能對大家有所幫助
    2014-10-10
  • Java通過調(diào)用FFMPEG獲取視頻時長

    Java通過調(diào)用FFMPEG獲取視頻時長

    這篇文章主要為大家詳細介紹了Java通過調(diào)用FFMPEG獲取視頻時長,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-04-04
  • 使用Java實現(xiàn)獲取文件MD5值工具類

    使用Java實現(xiàn)獲取文件MD5值工具類

    我們在工作中通常使用MD5對文件進行校驗完整性,比較,提高安全性等,這篇文章主要為大家詳細介紹了Java如何編寫一個實現(xiàn)獲取文件MD5值的工具,需要的可以參考下
    2023-12-12
  • java swing實現(xiàn)簡單的五子棋游戲

    java swing實現(xiàn)簡單的五子棋游戲

    這篇文章主要為大家詳細介紹了java swing實現(xiàn)簡單的五子棋游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-03-03

最新評論

武夷山市| 娱乐| 金塔县| 满洲里市| 蒲江县| 台北市| 晋江市| 宁强县| 青龙| 湖口县| 锦屏县| 鄯善县| 七台河市| 鄂托克前旗| 朝阳市| 藁城市| 石家庄市| 紫阳县| 三穗县| 梁平县| 芜湖县| 亳州市| 岳普湖县| 准格尔旗| 金昌市| 招远市| 鞍山市| 清水河县| 大宁县| 南川市| 额尔古纳市| 康平县| 绵阳市| 商水县| 邹城市| 奉新县| 曲周县| 清丰县| 红桥区| 诸暨市| 辉县市|