前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >自定义ClassLoader的实现

自定义ClassLoader的实现

作者头像
南风
发布2019-12-05 21:22:36
4.1K0
发布2019-12-05 21:22:36
举报
文章被收录于专栏:Java大联盟Java大联盟

ClassLoader 是 JVM 结构中很重要的一块,也可以说是整个 JVM 运行机制的入口,程序通过 ClassLoader 将编译好的字节码文件加载到内存中,生成 Class,进而创建对象,之后才能进行各种运算、解析,最终生成机器码提交到操作系统中。

JVM 结构如下图所示。

ClassLoader 有 4 种具体的分类:

1、BootstrapClassLoader

2、ExtClassLoader

3、AppClassLoader

4、自定义 ClassLoader

BootstrapClassLoader 用来加载 Java 的核心类库,即存放在 java.* 包中的字节码文件,如 java.util.List、java.io.InputStream、java.lang.Integer 等。

ExtClassLoader 用来加载 Java 的扩展类库,即存放在 javax.* 包中的字节码文件,如 javax.sql.DataSource、javax.net.SocketFactory 等。

AppClassLoader 用来加载当前程序所在目录的类,即开发者自己编写的 Java 文件对应的字节码文件。

自定义的 ClassLoader 指开发者根据具体需求编写的类加载器,可以实现定制化加载。

接下来我们来实现一个自定义的 ClassLoader,首先是准备工作,ClassLoader 的作用是将字节码文件加载到内存中,所有你得先有字节码文件。

1、创建一个 Java 文件。

代码语言:javascript
复制
public class HelloWorld{
  public HelloWorld(){
    System.out.println("创建了HelloWorld对象");
  }
}

2、将其编译成字节码文件。

代码语言:javascript
复制
javac HelloWorld.java

有了字节码文件,接下来就可以编写自定义 ClassLoader,并通过其加载字节码文件了,ClassLoader 具体的工作流程主要是通过两个方法完成类加载的,分别是 findClass 和 defineClass。

findClass 根据路径加载字节码文件,然后交给 defineClass,再把字节码转化为 Class。自定义 ClassLoader 需要开发者对 findClass 方法进行重写,完成加载字节码文件的操作,之后再将字节数据传给 ClassLoader 的 defineClass 方法即可,根据这个思路,我们来实现代码。

3、创建自定义 ClassLoader,并继承 ClassLoader。

代码语言:javascript
复制
import java.io.*;

public class MyClassLoader extends ClassLoader {
    private String path;

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

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        String classPath = path+name+".class";
        InputStream inputStream = null;
        ByteArrayOutputStream outputStream = null;
        try {
            inputStream = new FileInputStream(classPath);
            outputStream = new ByteArrayOutputStream();
            int temp = 0;
            while((temp = inputStream.read()) != -1){
                outputStream.write(temp);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                outputStream.close();
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        byte[] bytes = outputStream.toByteArray();
        return defineClass(name,bytes,0,bytes.length);
    }
}

在 findClass 方法中,我们通过 IO 流读取本地编译好的字节码文件,生成字节数组,再将字节数组传给 ClassLoader 的 defineClass 方法即可。

4、进行测试,实例化 MyClassLoader,并通过该实例化对象加载字节码文件获取 Class 对象。

代码语言:javascript
复制
public class Test {
    public static void main(String[] args) {
        MyClassLoader myClassLoader = new MyClassLoader("/Users/southwind/myjava/");
        try {
            Class clazz = myClassLoader.findClass("HelloWorld");
            System.out.println(clazz);
            System.out.println(clazz.getConstructor().newInstance());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5、运行结果如下图所示。

HelloWorld 字节码文件加载成功,以上就是自定义 ClassLoader 的用法,你学会了吗?

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java大联盟 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档