java虚拟机自定义类加载器

开发中的类几乎由上述3种类加载器互相配合加载,必要时可以自定义类加载器来指定类的加载方式

为什么要自定义类加载器
隔离加载器
多个框架包名和类型相同,类冲突,把类加载到不同的应用选中
如tomcat,内部自定义了好几中类加载器,用于隔离web应用服务器上的不同应用程序。
修改类加载的方式
除了Bootstrap加载器外,其他的加载并非一定要引入,根据实际情况在某个时间按需进行动态加载
扩展加载器:比如还可以从数据库、网络、或其他终端上加载
防止源码泄漏: java代码容易被编译和篡改,可以进行编译加密,类加载需要自定义还原加密字节码。

实现步骤
(1) 通过继承抽象类java.lang.ClassLoader的方式,实现自己的类加载器
(2) 在JDK1.2之前,在自定义类加载器时,总会去继承ClassLoader类并重写loaderClass()方法,从而实现自定义的类加载器, 但是在JDK1.2之后不再建议用户去覆盖loadClass()方法,在loadClass()里面有双亲委派机制的代码,而是建议把自定义的类加载逻辑写在findClass()方法中
(3) 在编写自定义类加载器时,若没有太过于复杂的需求,可以直接继承URLClassLoader类,这样就可以避免自己去编写findClass()方法及其获取字节码流的方式,使自定义类加载器编写更加简洁

public class MyClassLoader extends ClassLoader {

    // 字节码文件的路径
    private String codePath;

    public MyClassLoader(ClassLoader parent, String codePath) {
        super(parent);
        this.codePath = codePath;
    }

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

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        BufferedInputStream bis = null;
        ByteArrayOutputStream baos = null;
        try {
            String file =  codePath + name + ".class";
            bis = new BufferedInputStream(new FileInputStream(file));
            int len;
            byte[] data = new byte[1024];
            while ((len = bis.read(data)) != -1){
                baos.write(data,0,len);
            }
            // 获取内存中的字节数组
            byte[] bytes = baos.toByteArray();
            // 调用defineClass将字节数组转成Class实例
            Class<?> clazz = defineClass(null, bytes, 0, bytes.length);
            // 返回class对象
            return clazz;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                baos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

测试
public class MyClassLoaderTest {
    public static void main(String[] args) {
        // 在这个路径上放一个Test.class,注意不是Test.java.注意项目中不要写Test类
        MyClassLoader classLoader = new MyClassLoader("d:/");
        try {
            Class<?> clazz = classLoader.loadClass("Test");
            System.out.println("Test字节码是由" + clazz.getClassLoader().getClass().getName() + "加载的");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值