java 扩展类加载器_java实现自定义类加载器

bb8b448995ed1dc0d375d13cd9246e09.png

各类加载器虽然以父子相称,但是没有继承关系

(视频教程推荐:java课程)

点入ClassLoader的源码查看样例:*

 
  

* class NetworkClassLoader extends ClassLoader {

* String host;

* int port;

*

* public Class findClass(String name) {

* byte[] b = loadClassData(name);

* return defineClass(name, b, 0, b.length);

* }

*

* private byte[] loadClassData(String name) {

* // load the class data from the connection

*  . . .

* }

* }

*

只需继承CalssLoader,重写 findClass方法即可:package reflect;

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.util.ArrayList;

import java.util.List;

public class MyClassLoader extends ClassLoader{

// 用于保存加载的文件的大小

private int classSize;

// 新增的类加载路径

private static List paths = new ArrayList<>();

static {

paths.add("D:\\Users\\jeff.chan\\Desktop\\");

}

// 默认会将app类加载器做为该类加载器的父加载器

public MyClassLoader() {

}

public MyClassLoader(ClassLoader parent) {

super(parent);

}

@Override

protected Class> findClass(String name) throws ClassNotFoundException {

byte[] b = loadBinaryData(name);

// 打印执行标记

System.out.println("use custom classloader...");

return defineClass(name, b,0, classSize);

}

public byte[] loadBinaryData(String name) throws ClassNotFoundException{

String pathName = name.replaceAll("\\.", "/");

File file = null;

for (String path : paths) {

file = new File(path+pathName+".class");

if(file.exists() && file.isFile()){

break;

}

}

if(file==null || !file.isFile()){

throw new ClassNotFoundException();

}

// 读取文件的二进制信息

try (InputStream in = new FileInputStream(file)){

// 一般这个大小够了,这里是为了方便读取

// 文件的内容,所以一次性读入,并且将大小返回

// 用于defineClass

byte[] b = new byte[1024 * 1024 * 10];

classSize = in.read(b);

return b;

}catch (IOException ioException){

;

}

return null;

}

}

这里加入了一个MyClassLoader自定义类加载器,扫描的路径为:D:\\Users\\jeff.chan\\Desktop\\

那么新加入的类加载器就和app类加载器,扩展类加载器,启动类加载器一起起作用。

测试用例:package reflect;

public class Person {

private String name;

private String age;

public Person() {

}

public Person(String name, String age) {

this.name = name;

this.age = age;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getAge() {

return age;

}

public void setAge(String age) {

this.age = age;

}

@Override

public String toString() {

return "Person{" +

"name='" + name + '\'' +

", age='" + age + '\'' +

'}';

}

}

客户端:package reflect;

public class Client {

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

MyClassLoader classLoader = new MyClassLoader();

Class> aClass = classLoader.loadClass("reflect.Person");

System.out.println(aClass);

System.out.println(aClass.getClassLoader());

}

}

时直接运行代码:那么会输出

class reflect.Person

sun.misc.Launcher$AppClassLoader@18b4aac2

发现自己的类加载器根本不起作用。其实是因为双亲委托机制:

1、MyClassLoader 查看是否已经加载 -》 2、App类加载查看是否已经加载 -》3、 扩展类加载器查看是否已经加载

-》 4、启动类加载器查看是否已经加载,没有加载就尝试加载 -》 5、扩展类尝试加载 -》 6、app类加载尝试加载 -》 7、MyClassLoader尝试加载 -》 8、抛出找不到类的异常

上述的流程中,第6步会找到对应的类,所以就直接返回了,根本没有给MyClassLoader机会加载,所以才没有调用自定义的类加载器MyClassLoader。

如果想要加载的话,那么就到编译生成的Person.class移动到桌面reflect/Person.class下,执行结果:

use custom classloader...

class reflect.Person

reflect.MyClassLoader@135fbaa4

结果发现,自定义的类加载起作用了,其实就是上述的流程中的第7步,找到了相应的类的二进制文件,加载了进来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值