自定义类加载器+打破双亲委派模型

工作目录

在这里插入图片描述

自定义类加载器

package X.service;

import java.io.*;

public class MyClassLoader extends ClassLoader{
    public MyClassLoader(ClassLoader parent){
        super(parent);
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        //1.获取class文件二进制字节数组
        byte[] data = null;
        try{
            System.err.println("寻找名字为"+name + "的类"+"-------------------");
            // 将.转为双杠
            String namePath = name.replaceAll("\\.", "\\\\");
            String classFile = "D:\\HuaDong\\party\\test\\src\\"+ namePath + ".class";
            System.err.println("路径:"+classFile);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            FileInputStream fis = new FileInputStream(classFile);
            byte[] bytes = new byte[1024];
            int len = 0;
            while((len = fis.read(bytes)) != -1){
                baos.write(bytes,0,len);
            }
            data = baos.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 2.字节码加载到 JVM 的方法区,
        // 并在 JVM 的堆区建立一个java.lang.Class对象的实例
        // 用来封装 Java 类相关的数据和方法
        return super.defineClass(name,data,0,data.length);
    }

    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        System.err.println("使用自定义加载器-------------------");
        Class clazz = null;
        clazz = this.findClass(name);
        if(clazz != null){
            return clazz;
        }
        // 自己加载不了,再调用父类loadClass,保持双亲委托模式
        return super.loadClass(name, false);
    }
}

想加载的类

自定义加载器是加载相应的.class文件,使用javac编译.java文件得到.class文件

package X.entity;

public class Idiot {
    private String name;
    private String action;

    public Idiot(String name, String action) {
        this.name = name;
        this.action = action;
    }
}

WeiningPayServiceTest使用自定义类加载器

@Test
  void testMyClassLoader() throws ClassNotFoundException {
      MyClassLoader myClassLoader = new MyClassLoader(MyClassLoader.class.getClassLoader());
      System.err.println("MyClassLoader的父类加载器:"+myClassLoader.getParent());

      Class clazz = myClassLoader.loadClass("net.whir.hos.partyfund.entity.Idiot");
      System.err.println("类加载器:"+clazz.getClassLoader());
  }

测试结果

在这里插入图片描述可知其父类加载器是应用类加载器。
为什么要找Object.class,并且还找不到Object.class ?

因为java中所有类都继承了Object,而加载自定义类X.entity.Idiot;,之后还会加载其父类,而最顶级的父类Object是java官方的类,只能由BootstrapClassLoader加载。

修正

在上述结果上得知,目前要处理object.class加载不出来的问题,考虑将自定义类的加载器的父类设置为启动类加载器
1)修改自定义类加载器

@Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        //1.获取class文件二进制字节数组
        byte[] data = null;
        try{
            System.err.println("寻找名字为"+name + "的类"+"-------------------");
            if(name.startsWith("java.")){
                return null;
            }

2)修改父类

@Test
  void testMyClassLoader() throws ClassNotFoundException {
      MyClassLoader myClassLoader = new MyClassLoader(null);
      System.err.println("MyClassLoader的父类加载器:"+myClassLoader.getParent());

      Class clazz = myClassLoader.loadClass("X.entity.Idiot");
      System.err.println("类加载器:"+clazz.getClassLoader());
  }

结果

在这里插入图片描述
成功了,Idiot类由自定义的类加载器MyClassLoader加载的,并且其父级类加载器是启动类加载器,双亲委派模型被破坏了。

备注:
借鉴了这位作者的文章 https://www.cnblogs.com/shoshana-kong/p/17005974.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值