打破双亲委派机制有什么用_1.4 打破双亲委派机制

什么是打破双亲委派机制呢?

那么这里第一步, 我们需要知道什么是双亲委派机制?

前面已经说了什么是双亲委派机制了, 那打破是怎么回事呢?

比如, 我现在有一个自定义类加载器, 加载的是~/com/lxl/jvm/User1.class类, 而在应用程序的target目录下也有一个com/lxl/jvm/User1.class,  那么, 最终User1.class这个类将被哪个类加载器加载呢? 根据双亲委派机制, 我们知道, 他一定是被应用程序类加载器AppClassLoader加载, 而不是我们自定义的类加载器, 为什么呢? 因为他要向上寻找, 向下委托. 当找到了以后, 便不再向后执行了.

我们要打破双亲委派机制, 就是要让自定义类加载器来加载我们的User1.class, 而不是应用程序类加载器来加载

接下来分析, 如何打破双亲委派机制呢? 双亲委派机制是在哪里实现的? 是在ClassLoader类的loadClass(...)方法实现的. 如果我们不想使用系统自带的双亲委派模式, 只需要重新实现ClassLoader的loadClass(...)方法即可. 下面是ClassLoader中定义的loadClass()方法. 里面实现了双亲委派机制

下面给DefinedClassLoaderTest.java增加一个loadClass方法, 拷贝上面的代码即可. 删除掉中间实现双亲委派机制的部分

这里需要注意的是, com.lxl.jvm是自定义的类包, 只有我们自己定义的类才从这里加载. 如果是系统类, 依然使用双亲委派机制来加载.

来看看运行结果:

调用了user1的sout方法

com.lxl.jvm.DefinedClassLoaderTest

现在User1方法确实是由自定义类加载器加载的了

源码:

package com.lxl.jvm;

import java.io.FileInputStream;

import java.lang.reflect.Method;/**

* 自定义的类加载器*/

public classDefinedClassLoaderTest extends ClassLoader{privateString classPath;publicDefinedClassLoaderTest(String classPath) {this.classPath =classPath;

}/**

* 重写findClass方法

*

* 如果不会写, 可以参考URLClassLoader中是如何加载AppClassLoader和ExtClassLoader的

* @param name

* @return

* @throws ClassNotFoundException*/@Overrideprotected Class>findClass(String name) throws ClassNotFoundException {try{byte[] data =loadBytes(name);return defineClass(name, data, 0, data.length);

}catch(Exception e) {

e.printStackTrace();

}return null;

}private byte[] loadBytes(String name) throws Exception {//我们需要读取类的路径

String path = name.replace('.', '/').concat(".class");//String path = "";//去路径下查找这个类

FileInputStream fileInputStream = new FileInputStream(classPath + "/" +path);int len =fileInputStream.available();byte[] data = new byte[len];

fileInputStream.read(data);

fileInputStream.close();returndata;

}protected Class>loadClass(String name, boolean resolve)

throws ClassNotFoundException

{

synchronized (getClassLoadingLock(name)) {//First, check if the class has already been loaded

Class> c =findLoadedClass(name);if (c == null) {/**

* 直接执行findClass()...什么意思呢? 首先会使用自定义类加载器加载类, 不在向上委托, 直接由

* 自己执行

*

* jvm自带的类还是需要由引导类加载器自动加载*/

if (!name.startsWith("com.lxl.jvm")) {

c= this.getParent().loadClass(name);

}else{

c=findClass(name);

}

}if(resolve) {

resolveClass(c);

}returnc;

}

}public static voidmain(String[] args) throws Exception {

DefinedClassLoaderTest classLoader= new DefinedClassLoaderTest("/Users/luoxiaoli");

Class> clazz = classLoader.loadClass("com.lxl.jvm.User1");

Object obj=clazz.newInstance();

Method sout= clazz.getDeclaredMethod("sout", null);

sout.invoke(obj,null);

System.out.println(clazz.getClassLoader().getClass().getName());

}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值