java 自定义classloader_java 自定义类加载器

百度了一下,通篇全部都是启动类加载器,扩展类加载器,应用程序类加载器,还有就是双亲委托模式 。

可是一圈下来,新手们依然不知道如何自定义一个类加载器,来生动的展现什么是类加载器。

首先我们在E:upload下新建一个a/BB.java文件。

代码如下:

packagea;public classBB {privateString a;publicBB(){

}publicBB(String a){this.a=a;

}public static voidmain(String[] args) {

System.out.println("aaaaaaaaaa");

}

}

ab9124dfbca10d538a512be15ee3b1e9.png

编译后出现BB.class字节码文件

退回到上级目录,因为包是到a目录的。执行java a.BB;正确执行main方法

68c4f922c54c6e22840bcef9519ea2c7.png

现在我们回到IDea编辑器中,将BB.class文件读取到内存,并且利用反射进行实例化。

自定义类加载器   MyClassLoader.java

packagea;import java.io.*;importjava.lang.reflect.Field;public class MyClassLoader extendsClassLoader{

@Overrideprotected Class>findClass(String name) {byte[] bytes=null;//将点替换成斜杠

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

StringBuilder sb=new StringBuilder("E:");

sb.append(File.separator);

sb.append("upload");

sb.append(File.separator);

sb.append(fileName);

sb.append(".class");

fileName=sb.toString();try{

InputStream is=newFileInputStream(fileName);

ByteArrayOutputStream bos=newByteArrayOutputStream();byte[] buf=new byte[1024];int r=0;while ((r=is.read(buf))!=-1){

bos.write(buf,0,r);

}

bytes=bos.toByteArray();

}catch(FileNotFoundException e) {

e.printStackTrace();

}catch(IOException e) {

e.printStackTrace();

}return defineClass(name,bytes,0,bytes.length);

}public static void main(String[] args) throwsException{//自定义类加载器对象1

MyClassLoader c1=newMyClassLoader();

String className="a.BB";

//loadClass调用的就是findClass()

Class clazz1=c1.loadClass(className);//自定义类加载器对象2

MyClassLoader c2=newMyClassLoader();

Class clazz2=c2.loadClass(className);

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

System.out.println(clazz2.getClassLoader());if(clazz1!=clazz2){

System.out.println("不同的类加载器对象加载相同的class文件,会产生不同的类对象");

}

Object obj1=clazz1.getDeclaredConstructor(new Class[]{String.class}).newInstance("自定义加载器加载进内存的");

Field fa=clazz1.getDeclaredField("a");

fa.setAccessible(true);//将私有变量设置成可以访问的权限

System.out.println(fa.get(obj1));

}

}

执行结果:

e.MyClassLoader@2b193f2d

e.MyClassLoader@4dc63996

不同的类加载器加载相同的class文件,会产生不同的类对象

自定义加载器加载进内存的

很明显clazz1和clazz2是两个类。

给BB.java中构造器传入的字符串:“自定义加载器加载进内存的”   也在上面打印出来了。

注意:如果将a/BB.java文件拷贝到idea编辑器中。那么MyClassLoader中的findClass就不会执行了。

因为MyClassLoader c1和MyClassLoader c2都继承自ClassLoader,所以直接交给上级类加载器加载应用程序类加载器:Application ClassLoader;

应用程序类加载器会首先找到a/BB.class文件,并加入内存;此时就不会在继续x向下传播调用加载了。

类加载器在加载的时候虚拟机会首先调用加载器的私用方法loadClassInternal()

85881c2f5c9e94adeeb076ec79a95600.png

而这个方法唯一作用就是调用自己的loadClass()方法,如果loadClass()加载失败了,则会调用自己的findClass()。

loadClass()也能被重写,但是我们不会这样做,因为这样做的话,所有的类都会走这个方法来加载类;那么虚拟机内置的一些类也会用这个方法里面的逻辑来加载,固定会报错。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值