1.3 自定义类加载器 一. 自定义类加载器 二. 自定义类加载的父类为什么是appClassLoader?

前面说了类加载器的双亲委派机制, 也知道了一个类是如何被类加载器加载进来的. 接下来. 我们来看一看如何自定义类加载器

对于类加载器, 我们知道他的重点是loadClass(...)方法, 里面的双亲委派机制也是在loadClass方法里面实现的. loadClass方法里面实际上去加载类的是findClass()方法. 对于我们自定义的类加载器来说需要做到两点即可

1. 这个自定义的类加载器继承自ClassLoader

2. 这个类加载器要重写ClassLoader类中的findClass()方法

下面我自己定义了一个类加载器

1.3 自定义类加载器
一. 自定义类加载器
二. 自定义类加载的父类为什么是appClassLoader?

 第一步是继承ClassLoader类, 然后定义一个构造方法, 用来接收要加载的类名

1.3 自定义类加载器
一. 自定义类加载器
二. 自定义类加载的父类为什么是appClassLoader?

 这里有两步操作,

第一个是: 从类路径中读取要加载类的文件内容, 自定义

第二个是: 调用构造类的方法, 调用的系统的defineClass

记下来来看看自定义的loadByte是如何实现的

1.3 自定义类加载器
一. 自定义类加载器
二. 自定义类加载的父类为什么是appClassLoader?

 这里的实现就是找到类, 并且将类的内容读取出来, 转换成二进制的字节码, 返回

最后一部分就是如何调用了.

1.3 自定义类加载器
一. 自定义类加载器
二. 自定义类加载的父类为什么是appClassLoader?

 用类加载器加载类, 然后实例化, 使用反射机制调用User1 的方法sout

package com.lxl.jvm;

public class User1 {
    public void sout() {
        System.out.println("进入到User1");
    }
}

这里面System.out.println(clazz.getClassLoader().getClass().getName()); 获取当前类的类加载器, 猜一猜这里打印的会是谁?

1.3 自定义类加载器
一. 自定义类加载器
二. 自定义类加载的父类为什么是appClassLoader?

 看到了么? 是AppClassLoader, 为什么呢?

原因是我的项目里已经有一个类User1了

1.3 自定义类加载器
一. 自定义类加载器
二. 自定义类加载的父类为什么是appClassLoader?

 我们自定义类加载器的父类是AppClassLoader. 而程序代码中的User1刚好是被AppClassLoader加载, 因为找到了,所以就不会再去我们指定的文件夹中查找了

这就是类的双亲委派机制的特点呀.

那么如果我们将项目中的User1类删除掉, 这是类加载器是谁呢? 当然就是我们自定义的类加载器了.

那么问题来了, 自定义类加载器的父类为什么是AppClassLoader呢?

二. 自定义类加载的父类为什么是appClassLoader?

我们来看一下源码

我们自定义的类加载器, 继承自ClassLoader类加载器, 那么在加载自定义类加载器之前, 应该先加载父类ClassLoader.

首先会执行ClassLoader的无参的构造方法.

1.3 自定义类加载器
一. 自定义类加载器
二. 自定义类加载的父类为什么是appClassLoader?

 而无参的构造方法会调用自身的构造方法

1.3 自定义类加载器
一. 自定义类加载器
二. 自定义类加载的父类为什么是appClassLoader?

 里面有一个parent, 我们就是要看看这个parent到底是谁. 也就是要看看getSystemClassLoader是谁?

1.3 自定义类加载器
一. 自定义类加载器
二. 自定义类加载的父类为什么是appClassLoader?

1.3 自定义类加载器
一. 自定义类加载器
二. 自定义类加载的父类为什么是appClassLoader?

 之前我们已经研究过getClassLoader()这个方法了, 这里面定义的loadClass是谁呢?就是AppClassLoader.

1.3 自定义类加载器
一. 自定义类加载器
二. 自定义类加载的父类为什么是appClassLoader?

1.3 自定义类加载器
一. 自定义类加载器
二. 自定义类加载的父类为什么是appClassLoader?

 这就是为什么自定义class类加载器的父类是AppClassLoader的原因了