Classloader中文叫做类加载器,作用就是把编译好的class文件加载到jvm中。但是,在jvm启动的时候,并不是一次性全部加载的。

三个原生的类加载器

  • Bootstrap ClassLoader最顶层的类加载器,主要加载核心类库,即jre lib下面的jar包。
  • Extention ClassLoader扩展类加载器,加载jre lib ext下的jar包。
  • AppClassLoader应用类加载器,加载当前应用即classpath下的所有类。

AppClassLoader的父加载器(不是父类)是Extention ClassLoaderExtention ClassLoader的父加载器(不是父类)是Bootstrap ClassLoader
我们可以写一些代码来验证一下。

    public static void main(String[] args) {System.out.println(User.class.getClassLoader());System.out.println(RequestDTO.class.getClassLoader().getParent());System.out.println(RequestDTO.class.getClassLoader().getParent().getParent());}

其中User类是我们自己创建的一个类,运行结果如下:

sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@614ddd49
null

前面两个结果是预期之内,最后一个获取Extention ClassLoader的结果为null是为什么呢?
其实,Bootstrap ClassLoader是由C++编写的,它本身就是虚拟机的一部分,所以他并不是一个Java类,也就是无法在java代码中获取它的引用。

双亲委托

指的是类加载机制。
AppClassLoader加载class的时候,它首先会去缓存里面查这个类是不是已经加载过了,如果没有,则让自己的父加载器去加载,一直递归,直到Bootstrap,如果Bootstrap ClassLoader也判断这个类没有被加载过,则会去jre lib下面去加载。如果还没加载到,则让自己子类Extention ClassLoader去jre lib ext下加载,如果它也加载不到,则让它的子类AppClassLoader去classpath下加载。总结一句话就是,由下向上委托,由上向下查找
为什么是这样子可以从代码中体现。

ClassLoader类的loadclass方法

protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// First, check if the class has already been loaded//对应上面的先去缓存里面查找,底层是C的方法Class<?> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();try {if (parent != null) {//对应上面的让父加载器去查找,递归c = parent.loadClass(name, false);} else {//说明父加载器是Bootstrap ClassLoader,底层也是C的方法c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}if (c == null) {// If still not found, then invoke findClass in order// to find the class.long t1 = System.nanoTime();//由于是递归,对应上面的从上到下查找c = findClass(name);// this is the defining class loader; record the statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}if (resolve) {resolveClass(c);}return c;}}

自定义ClassLoader类

  • 所有自定义的ClassLoader类的父加载器默认都是AppClassLoader
  • 如果要自定义一个ClassLoader类,建议覆盖findClass()方法,而不要改写loadclass(),这样就可以保持双亲委派机制

实现

DiskClassLoader

package com.curtain.classloader;import java.io.*;/*** @Author Curtain* @Date 2022/11/1 16:11* @Description*/
public class DiskClassLoader extends ClassLoader {private String mLibPath;public DiskClassLoader(String mLibPath) {this.mLibPath = mLibPath;}@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {String fileName = getFileName(name);File file = new File(mLibPath, fileName);try{//通过流将class文件读取进来,通过defineClass方法加载class类FileInputStream is = new FileInputStream(file);ByteArrayOutputStream bos = new ByteArrayOutputStream();int len = 0;while ((len = is.read()) != -1){bos.write(len);}byte[] bytes = bos.toByteArray();bos.close();is.close();return defineClass(name, bytes, 0, bytes.length);} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return super.findClass(name);}private String getFileName(String name) {int index = name.lastIndexOf(".");if (index == -1) {return name + ".class";} else {return name.substring(index + 1) + ".class";}}
}

再写一个Test类,待会儿我们就用加载这个类。

package com.curtain.classloader;/*** @Author Curtain* @Date 2022/11/1 14:42* @Description*/
public class Test {public void say(){System.out.println("Say Hello");}
}

我们编译好Test类,将 class文件放在一个地方,比如,D盘下的lib文件夹。
最后就是测试类,DiskClassLoaderTest

package com.curtain.classloader;import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;/*** @Author Curtain* @Date 2022/11/1 16:19* @Description*/
public class DiskClassLoaderTest {public static void main(String[] args) {//创建自定义ClassLoader对象DiskClassLoader diskClassLoader = new DiskClassLoader("D:\\lib");try{//加载class文件Class c = diskClassLoader.loadClass("com.curtain.classloader.Test");if (c != null){try{Object o = c.newInstance();Method method = c.getDeclaredMethod("say", null);method.invoke(o, null);} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}} catch (ClassNotFoundException e) {e.printStackTrace();}}
}

运行结果就是成功执行了Test类里面的say()方法

Classloader整理相关推荐

  1. ClassLoader整理总结

    (1)jvm的装载过程以及装载原理 所谓装载就是寻找一个类或是一个接口的二进制形式并用该二进制形式来构造代表这个类或是这个接口的 class对象的过程, 其中类或接口的名称是给定了的.当然名称也可以通 ...

  2. Java面试题及答案整理(2022年140道)持续更新

    发现网上很多Java面试题都没有答案,所以花了很长时间搜集整理出来了这套Java面试题大全,希望对大家有帮助哈~博主已将这些面试题整理到一个网站上,每天更新 Java 面试题,目前有 1万多道 Jav ...

  3. Java面试题及答案整理(2022最新版) 持续更新

    发现网上很多Java面试题都没有答案,所以花了很长时间搜集整理出来了这套Java面试题大全,希望对大家有帮助哈~博主已将这些面试题整理到一个网站上,每天更新 Java 面试题,目前有 1万多道 Jav ...

  4. Java面试题及答案整理( 2022年最新版,持续更新)

    发现网上很多Java面试题都没有答案,所以花了很长时间搜集整理出来了这套Java面试题大全~ 这套互联网 Java 工程师面试题包括了:MyBatis.ZK.Dubbo.EL.Redis.MySQL. ...

  5. 常见Jvm面试题总结及答案整理 120道(持续更新)

    最新Jvm面试题总结及答案[附答案解析]Jvm面试题及答案2021,Jvm面试题最新面试题,Jvm面试题新答案已经全部更新完了,有些答案是自己总结的,也有些答案是在网上搜集整理的.这些答案难免会存在一 ...

  6. Java面试题及答案整理 140道( 2021年持续更新)

    发现网上很多Java面试题都没有答案,所以花了很长时间搜集整理出来了这套Java面试题大全,希望对大家有帮助哈~ 本人发现网上虽然有不少Java相关的面试题,但第一未必全,第二未必有答案,第三虽然有答 ...

  7. Class.forName 和 ClassLoader 到底有啥区别?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者 | 纪莫 来源 | https://www.cnblogs. ...

  8. 面试题:Class.forName 和 ClassLoader 有什么区别?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 来源:http://t.cn/AiQQ7dwi 在 java 中 ...

  9. 【JVM】肝了一周,吐血整理出这份超硬核的JVM笔记(升级版)!!

    JDK 是什么? JDK 是用于支持 Java 程序开发的最小环境. Java 程序设计语言 Java 虚拟机 Java API类库 JRE 是什么? JRE 是支持 Java 程序运行的标准环境. ...

最新文章

  1. 记录用户转成超级用户的文件名字_Linux学习手册(四)—用户及权限管理类命令...
  2. windows phone 8 使用页面传对象的方式 实现页面间的多值传递
  3. repo 的几个使用理解
  4. bzoj 1689: [Usaco2005 Open] Muddy roads 泥泞的路(模拟)
  5. 07年博客迁移:心情记事
  6. Power Integrations推出的全新CAPZero-3 X电容放电IC符合IEC60335标准
  7. 使用 Socket 通信实现 FTP 客户端程序
  8. java 命名规则_java中命名规范
  9. MatLAB从背景单一、物体相对简单且相互分离的图片中求其照片中物体的最小外接圆圆心、半径,并画出最小外接圆
  10. Python爬取房天下二手房信息
  11. 手写输入---随手写
  12. jpeg 与 png 图片格式的区别
  13. Android-关于将Excel表格中的数据展示到手机屏幕上的解决方案
  14. 无监督关键短语的生成问题博客02--extract.py的分析
  15. 论坛报名 | 群体智能
  16. MySql8JDBC操作
  17. 微信小程序不显示base64位图片
  18. 登录注册 图片验证码生成
  19. DDS信号发生器:直接数字式频率合成器 (Direct Digital Synthesizer)
  20. 左耳听风ARTS第1周

热门文章

  1. 蚂蚁区块链BaaS平台架构与实践
  2. helm模板开发-流程控制、作用域、循环、变量(三)
  3. Android耗电统计算法
  4. ecshopnbsp;二次开发nbsp;全集
  5. rimraf node_modules 删除报错 rimraf : 无法加载文件
  6. 拉格朗日乘子法、对偶、KTT
  7. 基于html5的五子棋游戏
  8. c语言数独出题程序,C语言实现的数独解题程序
  9. oracle HTTP Server安装和配置为集群代理(linux)
  10. 关键字 surper 和 this