当前位置:网站首页>自定义类加载器
自定义类加载器
2022-08-08 06:27:00 【写做四月一日的四月一日】
目录
类加载器
| 类加载器名 | 加载路径 |
| 启动类加载器(Bootstrap ClassLoader) | %JAVM_HOME%\jre\lib |
| 扩展类加载器(Extension ClassLoader) | %JAVM_HOME%\jre\lib\ext |
| 应用类加载器(AppClassLoader) | %classpath% |
自定义类加载器:扩展于ClassLoader类,可以自定义路径。
双亲委派机制
当使用类加载器时,会按照自定义类加载器->应用类加载器->扩展类加载器->启动类加载器的方式向上委托父类加载来加载需要加载的类,如果加载不到,再由子类加载器来加载,最后都没有加载到则抛出ClassNotFoundException异常。
双亲委派机制的优点
保证了安全性。
举例:如果不使用双亲委派机制,开发者可以自定义一个java.lang.String类来覆盖官方的java.lang.String,使用自定义类加载器完成类加载。密码一般都是以字符串形式存储的,开发者可以在自定义的String类型中完成诸如将密码发送给自己等操作。使用双亲委派机制,当使用自定义类加载器加载自定义的java.lang.String类时,最终会通过双亲委派机制委托启动类加载器完成官方的java.lang.String加载,无法覆盖,保证了安全性。
双亲委派机制源码简介
查看Classloader类的源码,根据注释说明可以知道loadClass()方法是完成类加载的方法。
loadClass()源码查看

查看findClass()方法

源码中只是抛出了一个FlassNotFoundException异常,我们需要重写这个方法。
自定义类加载
当官方提供的三个类加载器都无法满足我们的需求,我们就需要自定义类加载器。如实现框架时,我们用到了动态代理模式来生成一个新的代理类,这个代理类就需要通过自定义类加载器来加载到程序中来。
根据之前的分析,我们实现一个类加载器只需要两步:
1)写一个类继承Classloader类;
2)重写findClass()方法。
一、写一个测试用类
这个类在官方的三个加载器都加载不到的路径,并使用javac命令编译这个类。
为了方便起见,我只写了一个printHello()方法,在方法中打印一个"hello"。

public class TestEntity{
public void printHello(){
System.out.println("hello");
}
}二、写一个自定义类加载器
public class MyClassLoader extends ClassLoader{
//这个自定义类加载器加载的路径
private String path = "F:\\java_work\\Java_project\\classloaderTestEntity\\";
//类文件的后缀名
private String suffix = ".class";
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
//输入流,用于读入class文件
BufferedInputStream bis = null;
//输出流,用于承接class文件内容,并生成一个byte[]数组
ByteArrayOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(path + name + suffix));
bos = new ByteArrayOutputStream();
//记录当前读入的长度
int length = 0;
//存放读入数据的临时数组
byte[] temp = new byte[1024];
//读入class文件并写到输出流
while ((length = bis.read(temp)) != -1){
bos.write(temp,0,length);
}
//获取到class文件的byte[]数组
byte[] classDataArray = bos.toByteArray();
//通过defineClass()方法来将byte[]数组转为一个class类
return defineClass(name,classDataArray,0,classDataArray.length);
} catch (IOException e) {
e.printStackTrace();
}finally {
if (null != bis){
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != bis){
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//最后还没有找到出ClassNotFoundException异常
return super.findClass(name);
}
}
三、测试能否将测试用类加载到程序中
public class TestApp {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
//获取自定义类加载器
MyClassLoader myClassLoader = new MyClassLoader();
//加载TestEntity类
Class clazz = myClassLoader.loadClass("TestEntity");
//实例化TestEntity类
Object obj = clazz.newInstance();
//调用printHello方法
Method[] methods = obj.getClass().getDeclaredMethods();
for (Method method : methods) {
if ("printHello".equals(method.getName())){
method.invoke(obj);
}
}
}
}运行结果

成功打印了"hello",类加载完成。
边栏推荐
猜你喜欢
CSDN21天学习挑战赛之选择排序

P22 美颜相机——引入动态数组,优化重绘

【图形学】12 UnityShader语法入门

类与对象之动静态方法,继承,名字的查找顺序,经典类和新式类,派生方法

【图形学】08 3D坐标系的变换(一)

The code in Unity HDRP dynamically modifies the skybox and other environment parameters
![[Unity] C#使用委托事件与字典实现unity消息中心(观察者模式)](/img/30/da85bb67805b68296357bc8a72ed29.jpg)
[Unity] C#使用委托事件与字典实现unity消息中心(观察者模式)
![计算机网络 | 03.[HTTP篇] HTTP缓存技术](/img/ff/c8c6f044ccb5bdff76b7849537d396.png)
计算机网络 | 03.[HTTP篇] HTTP缓存技术

Unity_雷达图(属性图)+ UI动画

Unity—ParticleSystem(粒子系统)与Animator(动画状态机)批量管理器
随机推荐
最详细的Vivado安装教程
神经网络预测值几乎一样,神经网络为什么能预测
深度神经网络的训练过程,深度神经网络训练方法
NVIDIA CUDA Highly Parallel Processor Programming (VII): Parallel Mode: Prefix and
leetcode每日一题8.6(持续更新)
rhcsa——第二天
NVIDIA CUDA Highly Parallel Processor Programming (6): Parallel Mode: Convolution
CSDN21天学习挑战赛之顺序查找
[总结]Unity Console面板的问题汇总
Unity object color gradient effect (judgment logic implementation)
P23 传值和传引用
带头双向循环链表的增删查改
【图形学】03 数学部分(三、各种变换矩阵)
Unity_条形图(柱状图)+ UI动画
网络配置——静态路由内网以及外网连接
括号问题
The state machine control shift register multisim simulation in the process of state variables and state transition conditions don't match
Leetcode题目分享以及讲解
NVIDIA CUDA Highly Parallel Processor Programming (8): Parallel Mode: Histogram Calculation
文件IO实现图片的加密操作