自定义类加载器

什么是类加载器

类加载器:它的功能主要是负责从classpath所在的目录下加载class文件到内存中。
当在程序中获取到某个class文件对象(Class对象),这时可以调用其中的getClassLoader() 得到当前负责加载这个class文件的那个类加载器对象。

类加载器组织架构

在JDK中提供的最基础的三个类加载器,它们分别负责加载不同的class文件。
并且这三个类加载器,它们之间是继承关系。

bootstrap class loader(根类加载器):它是C语言编写的,在程序中我们是无法使用。也无法获取到。
它负责加载JDK中的的jre中的lib目录下的所有jar包。

ExtClassLoader(扩展类加载器):它是Java语言编写的。它负责加载jdk目录下jre中的ext文件中的所有jar包。

AppClassLoader(应用程序类加载器):它是Java语言编写的。它用于加载开发人员自己写的程序。

类加载器的委托机制

AppClassLoader 在加载某个类之前,它不会直接去加载class文件,而是将任务交给ExtClassLoader加载。而ExtClassLoader也不加载,继续将加载任务交给bootstrap class loader加载。如果bootstrap class loader找到了就加载,如果没有找到,会告诉ExtClassLoader需要加载。ExtClassLoader它会在自己加载的范围中找能不能加载,如果可以就加载,如果不可以,就将加载的任务交给AppClassLoader,只能AppClassLoader加载。

自定义类加载器

/*
 * 演示自定义类加载器
 *  1、继承ClassLoader
 *  2、复写其中的findClass(String name)
 *       String name 给出需要加载的class文件所在的目录
 */
public class MyClassLoader extends ClassLoader{

    //复写findClass方法
    public Class<?> findClass(String name) throws ClassNotFoundException {

        //定义io流读取指定的class文件中的数据

        try {
            //字节输入流,用于读取class文件中的数据
            FileInputStream fis = new FileInputStream(name);
            //ByteArrayOutputStream 它是一个输出流,会将数据写到内存中的一个byte数组中
            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            //使用io的模版代码读写数据
            byte[] buf = new byte[1024];
            int len = 0;
            while( ( len = fis.read( buf ) ) != -1 ){
                baos.write(buf, 0, len);
            }
            //循环结束,已经将class文件中的数据全部读取到内存中的一个数组中
            //将数组中的内容转成Class文件对象
            byte[] bs = baos.toByteArray();

            //调用defineClass 将字节数组中的数据转成Class对象
            return defineClass(null, bs, 0, bs.length);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("加载失败!!!");
        }
    }
}

调用自定义类加载器

package cn.itcast.sh.classloader;

import cn.itcast.sh.domain.Person;

public class Test {
    public static void main(String[] args) throws Exception {

        MyClassLoader cl = new MyClassLoader();
        Class clazz = cl.findClass("D:/JavaEE3/day23/bin/cn/itcast/sh/domain/Person.class");
        System.out.println(clazz);

        Object obj = clazz.newInstance();
        System.out.println(obj.getClass().getClassLoader());
        //下面的Person是被谁加载的?
        Person p = new Person();
        System.out.println(p.getClass().getClassLoader());
        //如果一个class文件被不同的类加载器加载,它们得到的对象也无法进行转换
        p = (Person) obj;

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值