我的编程空间,编程开发者的网络收藏夹
学习永远不晚

整理Java中的ClassLoader核心知识点

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

整理Java中的ClassLoader核心知识点

[[350691]]

JDK 和 JRE 的作用

  • JDK 提供了 java 的编程环境,它包含编译调试的环境功能,包含 JRE(JDK 目录中的 JRE 为专用 JRE,而安装后与 JDK 同目录的 JRE 为公用 JRE)。开发时一般运行的是 JDK 专用JRE,而运行外部程序时一般运行的是公用 JRE,实现了分工不同的 jre 负责各自范围的内容。
  • JRE 提供了 JAVA 程序运行的必要环境平台

JAVAHOME、PATH、CLASSPATH

  • JAVAHOME: JDK安装的位置路径,如:D:\Program Files\Java\jdk1.8.0_241
  • PATH: 配置后运行 bin 中的命令不需要补全全路径,如可以在任意的位置运行 java 和 javac 命令, %JAVA_HOME%\bin;
  • CLASSPATH:指向jar包路径 %JAVA_HOME%\lib;

类加载器的种类

在JVM中有三类ClassLoader构成:

  • Bootstrap ClassLoader 启动类(或根类)加载器
  • Extention ClassLoader 扩展的类加载器
  • Appclass Loader 应用类加载器

(1) Bootstrap ClassLoader

Bootstrap ClassLoader 最顶层的类加载器,主要加载核心类库 %JRE_HOME%\lib 下的 rt.jar、resources.jar、charsets.jar 和 class文件等。

  1. //执行 
  2. System.out.println(System.getProperty("sun.boot.class.path")); 
  3. //输出结果 
  4. D:\Program Files\Java\jdk1.8.0_241\jre\lib\resources.jar; 
  5. D:\Program Files\Java\jdk1.8.0_241\jre\lib\rt.jar; 
  6. D:\Program Files\Java\jdk1.8.0_241\jre\lib\sunrsasign.jar; 
  7. D:\Program Files\Java\jdk1.8.0_241\jre\lib\jsse.jar; 
  8. D:\Program Files\Java\jdk1.8.0_241\jre\lib\jce.jar; 
  9. D:\Program Files\Java\jdk1.8.0_241\jre\lib\charsets.jar; 
  10. D:\Program Files\Java\jdk1.8.0_241\jre\lib\jfr.jar; 
  11. D:\Program Files\Java\jdk1.8.0_241\jre\classes 

(2) Extention ClassLoader

Extention ClassLoader 扩展的类加载器,主要加载目录 %JRE_HOME%\lib\ext 目录下的jar包和class文件。

  1. //执行 
  2. System.out.println(System.getProperty("java.ext.dirs")); 
  3. //输出 
  4. D:\Program Files\Java\jdk1.8.0_241\jre\lib\ext;C:\Windows\Sun\Java\lib\ext 

(3) Appclass Loader

Appclass Loader也称为SystemAppClass 加载当前应用的classpath的所有类。

类加载器的执行顺序

除启动类加载器(Bootstrap ClassLoader)外,扩展类加载器和应用类加载器都是通过类sun.misc.Launcher进行初始化,而Launcher类则由启动类加载器进行加载。Launcher相关代码如下:

  1. public Launcher() { 
  2.     Launcher.ExtClassLoader var1; 
  3.     try { 
  4.         //初始化扩展类加载器,构造函数没有入参,无法获取启动类加载器 
  5.         var1 = Launcher.ExtClassLoader.getExtClassLoader(); 
  6.     } catch (IOException var10) { 
  7.         throw new InternalError("Could not create extension class loader", var10); 
  8.     } 
  9.  
  10.     try { 
  11.         //初始化应用类加载器,入参为扩展类加载器 
  12.         this.loader = Launcher.AppClassLoader.getAppClassLoader(var1); 
  13.     } catch (IOException var9) { 
  14.         throw new InternalError("Could not create application class loader", var9); 
  15.     } 
  16.  
  17.     // 设置上下文类加载器 
  18.     Thread.currentThread().setContextClassLoader(this.loader); 
  19.      
  20.    //... 

加载顺序:Bootstrap CLassloder > Extention ClassLoader > AppClassLoader

父加载器概念

AppClassLoader 和 ExtClassLoader 都继承了 URLClassLoader。每个类加载器都有一个父加载器(注意:父类和父加载器是两个不同的概念),可通过 getParent() 获取父类加载器。

  1. System.out.println("ClassLoader is:"+cl.toString()); 
  2. System.out.println("ClassLoader\'s parent is:"+cl.getParent().toString());System.out.println("ClassLoader\'s grand father is:"+cl.getParent().getParent().toString()); 
  • AppClassLoader 的父加载器是ExtClassLoader
  • ExtClassLoader的父加载器是Bootstrap ClassLoader(上面代码输出 ExtClassLoader 为null 是因为 Bootstrap ClassLoader 本身不是一个Java 类所致)
  • Bootstrap ClassLoader是由C/C++编写的,它本身是虚拟机的一部分,所以它并不是一个JAVA类,也就是无法在java代码中获取它的引用,JVM启动时通过Bootstrap类加载器加载rt.jar等核心jar包中的class文件,之前的int.class,String.class都是由它加载。然后呢,我们前面已经分析了,JVM初始化sun.misc.Launcher并创建Extension ClassLoader和AppClassLoader实例。并将ExtClassLoader设置为AppClassLoader的父加载器。Bootstrap没有父加载器,但是它却可以作用一个ClassLoader的父加载器。

双亲委派

双亲委派模型:当一个类加载器接收到类加载请求时,会先请求其父类加载器加载,依次递归,当父类加载器无法找到该类时(根据类的全限定名称),子类加载器才会尝试去加载。

时序图

为什么使用双亲委派模型?

双亲委派模型是为了保证Java核心库的类型安全。所有Java应用都至少需要引用java.lang.Object类,在运行时这个类需要被加载到Java虚拟机中。如果该加载过程由自定义类加载器来完成,可能就会存在多个版本的java.lang.Object类,而且这些类之间是不兼容的。

通过双亲委派模型,对于Java核心库的类的加载工作由启动类加载器来统一完成,保证了Java应用所使用的都是同一个版本的Java核心库的类,是互相兼容的。

自定义类加载器

不管是Bootstrap ClassLoader还是ExtClassLoader等,这些类加载器都只是加载指定的目录下的jar包或者资源。如果我们需要动态加载比如从指定目录中加载一个class文件,这时候通过自定义类加载器可以实现。

自定义类加载器只需要继承java.lang.ClassLoader类,然后重写findClass(String name)方法即可,在方法中指明如何获取类的字节码流。如果要破坏双亲委派规范的话,还需重写loadClass方法(双亲委派的具体逻辑实现)。但不建议这么做。

  1. public class ClassLoaderTest extends ClassLoader { 
  2.  
  3.     private String classPath; 
  4.  
  5.     public ClassLoaderTest(String classPath) { 
  6.         this.classPath = classPath; 
  7.     } 
  8.  
  9.      
  10.     @Override 
  11.     protected Class> findClass(String name) throws ClassNotFoundException { 
  12.         // 获取类的class文件字节数组 
  13.         byte[] classData = getClassData(name); 
  14.         if (classData == null) { 
  15.             throw new ClassNotFoundException(); 
  16.         } else { 
  17.             // 生成class对象 
  18.             return defineClass(name, classData, 0, classData.length); 
  19.         } 
  20.     } 
  21.  
  22.      
  23.     private byte[] getClassData(String className) { 
  24.         // 读取类文件的字节 
  25.         String path = classNameToPath(className); 
  26.         try { 
  27.             InputStream is = new FileInputStream(path); 
  28.             ByteArrayOutputStream stream = new ByteArrayOutputStream(); 
  29.             byte[] buffer = new byte[2048]; 
  30.             int num = 0
  31.             // 读取类文件的字节码 
  32.             while ((num = is.read(buffer)) != -1) { 
  33.                 stream.write(buffer, 0, num); 
  34.             } 
  35.             return stream.toByteArray(); 
  36.         } catch (IOException e) { 
  37.             e.printStackTrace(); 
  38.         } 
  39.         return null; 
  40.     } 
  41.  
  42.      
  43.     private String classNameToPath(String className) { 
  44.         return classPath + File.separatorChar 
  45.                 + className.replace('.', File.separatorChar) + ".class"; 
  46.     } 
  47.  
  48.     public static void main(String[] args) { 
  49.         String classPath = "/Users/zzs/my/article/projects/java-stream/class="lazy" data-src/main/java/"
  50.         ClassLoaderTest loader = new ClassLoaderTest(classPath); 
  51.  
  52.         try { 
  53.             //加载指定的class文件 
  54.             Class> object1 = loader.loadClass("com.secbro2.classload.SubClass"); 
  55.             System.out.println(object1.newInstance().toString()); 
  56.         } catch (Exception e) { 
  57.             e.printStackTrace(); 
  58.         } 
  59.     } 

 

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

整理Java中的ClassLoader核心知识点

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

整理Java中的ClassLoader核心知识点

本文整理了基于 JDK8 的 ClassLoader 核心知识点,包括 JVM 中 ClassLoader 种类、ClassLoader 执行顺序、父加载器概念、双亲委派机制、自定义类加载器。

Java中的ClassLoader核心知识点有哪些

这篇文章主要介绍“Java中的ClassLoader核心知识点有哪些”,在日常操作中,相信很多人在Java中的ClassLoader核心知识点有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中的C
2023-06-16

聊一聊 Java 一些核心知识点

看到有写读者希望整理关于Java基础的面试题,所以我将早期的文章进行梳理整理了一份关于Java基础的面试题。
Java开发2024-11-28

java多线程的核心知识点是什么

这篇文章主要介绍“java多线程的核心知识点是什么”,在日常操作中,相信很多人在java多线程的核心知识点是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”java多线程的核心知识点是什么”的疑惑有所帮助!
2023-06-20

讲解 Zookeeper 的五个核心知识点

ZooKeeper 是一个开源的分布式协调框架,它的定位是为分布式应用提供一致性服务,是整个大数据体系的管理员。ZooKeeper 会封装好复杂易出错的关键服务,将高效、稳定、易用的服务提供给用户使用。
Zookeeper2024-12-03

测试开发必须掌握的重要知识点-Spring的核心知识点 -Java注解@

Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。Annotation 是一个辅助类,它在 Junit、Struts、Spring 等工具框架中被广泛使用。

C++ 思维导图:全面整理编程核心知识

目标:构建一个全面的 c++++ 思维导图,涵盖基本语法、面向对象编程、数据结构、算法以及输入输出。思维导图包括:基本语法:包含数据类型、变量、操作符、控制流和函数。面向对象编程(oop):包含类和对象、继承、多态和虚函数。数据结构:包含数
C++ 思维导图:全面整理编程核心知识
2024-05-24

聊聊Axios中值得学习的核心知识点

Axios 是一个基于 Promise 的 HTTP 客户端,同时支持浏览器和 Node.js 环境。它是一个优秀的 HTTP 客户端,被广泛地应用在大量的 Web 项目中。

spark的基础知识点整理

这篇文章主要介绍“spark的基础知识点整理”,在日常操作中,相信很多人在spark的基础知识点整理问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”spark的基础知识点整理”的疑惑有所帮助!接下来,请跟着小编
2023-06-02

Java 异常的知识整理

Java 异常1.继承关系2.Error程序运行时发生的无法被处理的错误,一旦发生,JVM终止执行。3.ExceptionException是程序编译与运行时出现的一种错误,一旦出现,JVM将告知程序员处理。分为两种:运行时异常:在运行时发
2023-05-31

linux的基础知识点整理

这篇文章主要介绍“linux的基础知识点整理”,在日常操作中,相信很多人在linux的基础知识点整理问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”linux的基础知识点整理”的疑惑有所帮助!接下来,请跟着小编
2023-06-13

python整数和变量的知识点整理

这篇文章主要讲解了“python整数和变量的知识点整理”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“python整数和变量的知识点整理”吧!1.整数Python可以处理任意大小的整数,当然包
2023-06-04

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录