自定义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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章