自定義ClassLoader

ClassLoader是整個JVM運行機制的入口,程序通過ClassLoader將編譯好的字節碼文件加載到內存中,生成Class,進而創建對象,之後才能進行各種運算、解析,最終生成機器碼提交到操作系統中;

ClassLoader的作用是將字節碼文件加載到內存中,所以要先有字節碼文件
1、創建java文件

public class FileJava {

    public FileJava() {
        System.out.println("hhehhehe");
    }
}

特別需要注意的是:
該文件不能在idea中創建,否則會在運行程序的時候被編譯到用戶類路徑(classpath)下,那麼還是會被AppClassLoader加載;

而且如果將其建立在IDEA中,在編譯完該文件之後,其class文件會存在於該項目的src同等階級的out/production/目錄下,如果使用的是該class路徑,運行時也會報java.lang.NoClassDefFoundError錯誤;

我將該文件建立在了D盤下的ClassLoaderBySelf文件夾下;

2、編譯java文件爲字節碼文件

使用命令:javac FileJava.java

3、創建自定義ClassLoader,並繼承ClassLoader

ClassLoader具體的工作流程主要是通過兩個方法完成類加載的,分別是findClass和defineClass;
findClass根據路徑加載字節碼文件,然後交給defineClass,再把字節碼文件轉化爲class。
自定義ClassLoader需要開發者對findClass方法進行重寫,完成加載字節碼文件的操作,之後再將字節數據傳給ClassLoader的defineClass方法即可;

import java.io.*;

public class MyClassLoader extends ClassLoader {

    private String myPath;//文件路徑

    public MyClassLoader( String myPath) {
        this.myPath = myPath;
    }

    @Override
    protected Class<?> findClass(String name)  throws  ClassNotFoundException{
        //name是文件名
        String  classPath=myPath+name+".class";
        //System.out.println(classPath);
        InputStream in=null;
        ByteArrayOutputStream out=null;

        try {
            in = new FileInputStream(classPath);
            out=new ByteArrayOutputStream();
            int value=-1;
            while ((value=in.read())!=-1){
               out.write(value);
             }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(out!=null){
                    out.close();
                }
                if(in!=null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        byte[] bytes= out.toByteArray();

        return defineClass(name,bytes,0,bytes.length);
    }
}

4、進行測試
實例化MyClassLoader,並通過該實例化對象加載字節碼文件獲取Class對象

public class Test {
    public static void main(String[] args) {
        MyClassLoader myClassLoader=new MyClassLoader("D:/ClassLoaderBySelf/");
        try {
            Class classz=myClassLoader.loadClass("FileJava");
            System.out.println(classz);
            System.out.println(classz.getConstructor().newInstance());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

截圖:
在這裏插入圖片描述

發佈了53 篇原創文章 · 獲贊 2 · 訪問量 3011
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章