当前位置: 首页 > news >正文

JVM:类加载器

文章目录

  • 一、什么是类加载器
  • 二、类加载器的应用场景
  • 三、类加载器的分类
    • 1、分类
    • 2、启动类加载器
    • 3、Java中的默认类加载器
      • (1)扩展类加载器
      • (2)应用程序类加载器
      • (3)arthas中类加载器相关的功能
  • 四、双亲委派机制
    • 1、介绍
    • 2、双亲委派的作用
      • (1)保证类加载的安全性
      • (2)避免重复加载
    • 3、Java中如何使用代码方式去主动加载一个类
    • 4、类加载器
      • (1)介绍
      • (2)arthas中类加载器相关的功能
  • 五、打破双亲委派机制
    • 1、打破双亲委派机制的三种方式
      • (1)自定义类加载器
      • (2)线程上下文类加载器
      • (3)Osgi框架的类加载器
  • 六、JDK9之后的类加载器

一、什么是类加载器

类加载器(ClassLoader)是Java虚拟机提供给应用程序去实现获取类和接口字节码数据的技术。类加载器只参与加载过程总的字节码获取并加载到内存这一部分。
在这里插入图片描述

二、类加载器的应用场景

在这里插入图片描述

三、类加载器的分类

1、分类

  • 类加载器分为两类,一类是Java代码中实现的,一类是Java虚拟机底层源码实现的。
    在这里插入图片描述
  • 类加载器的设计JDK8和8之后的版本差别较大,JDK8及之前的版本默认的类加载器有如下几种:
    在这里插入图片描述
  • 类加载器的详细信息可以通过Arthas classloader命令查看:classloader - 查看classloader的继承树,urls,类加载信息,使用classloader去getResource。
    在这里插入图片描述

2、启动类加载器

  • 启动类加载器(Boostrap ClassLoader)是由HotSpot虚拟机提供的、使用C ++编写的类加载器。
  • 默认加载Java安装目录/jre/lib下的类文件,比如rt.jar,tool.jar,resource.jar等。
    在这里插入图片描述
    通过启动类加载器去加载用户jar包
  • 放入jre/lib下进行扩展:不推荐,尽可能不要去更改JDK安装目录中的内容,会出现即使放进去由于文件名不匹配的问题也不会正常被加载。
  • 使用参数进行扩展:推荐,使用-Xbootclasspath/a:jar包目录/jar包名,进行扩展。

3、Java中的默认类加载器

  • 扩展类加载器和应用程序类加载器都是JDK中提供的、使用Java编写的类加载器。
  • 他们的源码都位于sun.misc.Launcher中,是一个静态内部类。继承自URLClassLoader。具备通过目录或者指定jar包将字节码文件加载到内存中。
    在这里插入图片描述

(1)扩展类加载器

  • 扩展类加载器(Extension Class Loader)是JDK中提供的、使用Java编写的类加载器。
  • 默认加载Java安装目录/jre/lib/ext下的类文件。
    在这里插入图片描述

通过扩展类加载器去加载用户jar包

  • 放入/jre/lib/ext下进行扩展:不推荐,尽可能不要去更改JDK安装目录中的内容。
  • 使用参数进行扩展:推荐,使用**-Djava.ext.dirs=jar包目录**,进行扩展,这种方式会覆盖原始目录,可以用;(windows)、:(macos/linux)追加原始目录。

(2)应用程序类加载器

加载classpath下的类文件。

(3)arthas中类加载器相关的功能

类加载器的加载路径可以通过classloader -c hash值查看:
在这里插入图片描述

四、双亲委派机制

1、介绍

由于Java虚拟机中有多个类加载器,双亲委派机制的核心是解决一个类到底由谁加载的问题。双亲委派机制指的是:当一个类加载器收到加载类的任务时,会自底向上查找是否加载过,再由顶向下进行加载。向上查找如果已经加载过,就直接返回Class对象,加载过程结束。这样就能避免一个类重复加载。如果所有的父类加载器都无法加载该类,则由当前类加载器自己尝试加载。所以看上去是指顶向下尝试加载。
在这里插入图片描述

2、双亲委派的作用

(1)保证类加载的安全性

通过双亲委派机制避免恶意代码替换JDK中的核心类库,比如java.lang.String,确保核心类库的完整性和安全性。

(2)避免重复加载

双亲委派机制可以避免同一个类被多次加载。

3、Java中如何使用代码方式去主动加载一个类

  • 使用Class.forName方法,使用当前类的类加载器去加载指定的类。
    public static Class<?> forName(String className)throws ClassNotFoundException {Class<?> caller = Reflection.getCallerClass();return forName0(className, true, ClassLoader.getClassLoader(caller), caller);}private static native Class<?> forName0(String name, boolean initialize,ClassLoader loader,Class<?> caller)throws ClassNotFoundException;
  • 获取到类加载器,通过类加载器的loadClass方法指定某个类加载器加载。

4、类加载器

(1)介绍

每个Java实现的类加载器中保存了一个成员变量叫“父”类加载器,可以理解为他的上级,不是继承关系。
在这里插入图片描述

  • 应用程序类加载器的parent父类加载器时扩展类加载器,而扩展类加载器parent是空,但是在逻辑上,扩展类加载器依然会把启动类加载器当成父类加载器处理。
  • 启动类加载器使用C++编写,没有父类加载器。
    在这里插入图片描述
    下面体现了启动类加载器、扩展类加载器和应用程序类加载器的层级关系。
    在这里插入图片描述

(2)arthas中类加载器相关的功能

类加载器的父子关系可以通过classloader -t查看
在这里插入图片描述

五、打破双亲委派机制

1、打破双亲委派机制的三种方式

(1)自定义类加载器

  • 自定义类加载器并且重写loadClass方法,就可以将双亲委派机制的代码去除。
  • Tomcat通过这种方式实现应用之间的类隔离。
    • Tomact使用了自定义类加载器来实现应用之间类的隔离。每个应用会有一个独立的类加载器加载对应的类。
      在这里插入图片描述
  • 先来分析ClassLoader的原理,ClassLoader中包含了4个核心方法。
  • 双亲委派机制的核心代码位于loadClass方法中。
    在这里插入图片描述
  • 阅读双亲委派机制的核心代码,分析如何通过自定义的类加载器打破双亲委派机制。
  • 打破双亲委派机制就是将下边的一段代码重新实现。
    在这里插入图片描述

自定义类加载器默认的父类加载器

  • 以JDK8为例,ClassLoader类中提供了构造方法设置parent的内容。
    在这里插入图片描述

  • 这个构造方法由另外一个构造方法调用,其中父类加载器由getSystemClassLoader方法设置,该方法返回的是AppClassLoader。
    在这里插入图片描述

两个自定义类加载器加载相同限定名类不会冲突

  • 在同一个Java虚拟机中,只有相同了加载器+相同的类限定名才会被认为是同一个类。
  • 在Arthas中使用sc -d 类名的方式查看具体的情况。

(2)线程上下文类加载器

利用上下文类加载器加载类,比如JDBC和JNDI。

(3)Osgi框架的类加载器

历史上Osgi框架实现了一套新的类加载机制,允许同级之间委托进行类的加载。

六、JDK9之后的类加载器

  • 由于JDK9引入了module的概念,类加载器在设计上发生了很多的变化。
    在这里插入图片描述
    • 启动类加载器使用Java编写,位于jdk.internal.loader.ClassLoaders类中。java中的BootClassLoader继承自BuiltinClassLoader实现从某块中找到要加载的字节码资源文件。启动类加载器依然无法通过java代码获取到,返回的仍然是null,保持了统一。
      在这里插入图片描述
  • 扩展类加载器被替换成了平台类加载器(Platform Class Loader)。平台类加载器遵循模块化方式加载字节码文件,所以继承关系从URLClassLoader变成了BuiltinClasLoader,BuiltinClasLoader实现了从模块中加载字节码文件。平台类加载器的存在更多的是为了与老版本的设计方案兼容,自身没有特殊的逻辑。
    在这里插入图片描述
http://www.lryc.cn/news/400096.html

相关文章:

  • 支持向量机 (support vector machine,SVM)
  • 宝塔面板以www用户运行composer
  • 昇思25天打卡营-mindspore-ML- Day24-基于 MindSpore 实现 BERT 对话情绪识别
  • 【精品资料】模块化数据中心解决方案(33页PPT)
  • N6 word2vec文本分类
  • excel、word、ppt 下载安装步骤整理
  • 【python学习】标准库之日期和时间库定义、功能、使用场景和示例
  • Android --- Kotlin学习之路:基础语法学习笔记
  • 嵌入式智能手表项目实现分享
  • `nmap`模块是一个用于与Nmap安全扫描器交互的库
  • JVM系列 | 对象的创建与存储
  • 【JavaScript 算法】快速排序:高效的排序算法
  • Excel如何才能忽略隐藏行进行复制粘贴?
  • 行人越界检测 越线 越界区域 多边形IOU越界判断
  • 「UCD」浅谈蓝湖Figma交互设计对齐
  • VUE3 播放RTSP实时、回放(NVR录像机)视频流(使用WebRTC)
  • [PaddlePaddle飞桨] PaddleOCR-光学字符识别-小模型部署
  • Python应用开发——30天学习Streamlit Python包进行APP的构建(15):优化性能并为应用程序添加状态
  • python实现openssl的EVP_BytesToKey及AES_256_CBC加解密算法
  • 基于SpringBoot+VueJS+微信小程序技术的图书森林共享小程序设计与实现
  • 【css】image 使用 transform:scale 放大后显示不全的问题
  • 损失函数简介
  • 2023睿抗CAIP-编程技能赛-本科组省赛(c++)
  • 现在国内的ddos攻击趋势怎么样?想了解现在ddos的情况该去哪看?
  • 微服务到底是个什么东东?
  • C++笔试强训5
  • 初学51单片机之UART串口通信
  • 数据结构——查找(线性表的查找与树表的查找)
  • MySQL入门学习-深入索引.组合索引
  • RABBITMQ的本地测试证书生成脚本