JVM学习-详解类加载器(一)

类加载器

  • 类加载器是JVM执行类加载机制的前提
ClassLoader的作用
  • ClassLoader是Java的核心组件,所有的Class都是由ClassLoader进行加载的,ClassLoader负责通过各种方式将Class信息的二进制数据流读入JVM内部,转换为一个与目标类型对应的java.lang.Class对象实例,然后交给Java虚拟机进行链接,初始化等操作,因此ClassLoader整个装载阶段,只能影响类的加载,而无法通过ClassLoader去改变类的链接和初始化行为,至于是否可以运行,由Execution Engine决定
    在这里插入图片描述
  • 类加载器最早在java1.0版本中,那时只是单纯地为了满足Java Applet应用而被研发出来,但如今类加载器却在OSGi,字节码加解密领域大放异彩,这主要归功于Java虚拟机的设计者们当初在设计类加载器的时候,并没有考虑将它绑定在JVM内部,这样做的好处就是能够更加灵活和动态执行类加载操作。
类加载分类
显式加载
  • 显示加载指的是在代码中通过Classloader加载class对象,如直接使用Class.forName(name)或this.getClass().getClassLoader().loadClass()加载class对象
隐式加载
  • 隐式加载则不直接在代码中调用ClassLoader的方法加载class对象,而是通过虚拟机自动加载到内存中,如在加载某个类的class文件时,该类的class文件中引用了另外一个类的对象,此时额外引用的类将通过JVM自动加载到内存中
类加载必要性
  • 避免在开发中遇到java.lang.ClassNotFoundException异常或java.lang.NoClassDefFoundError异常时,手足无措,只有了解类加载器的加载机制才能在出现异常时根据错误异常日志定位问题和解决问题
  • 需要支持类的动态加载或需要对编译后的字节码文件进行加密操作时,就需要与类加载器打交道了
  • 开发人员可以在程序中编写自定义类加载器来重新定义类的加载规则,以便实现一些自定义的处理逻辑
命名空间
何为类的唯一性
  • 对于任意一个类,都需要加载它的类加载器和这个类本身一同确认其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间,**比较两个类是否相等,只有在这两个类是由同一个类加载器加载的前提下才有意义。**否则,即使这两个类源自同一个Class文件,被同一个虚拟机加载,只要加载他们的类加载器不同,那这两个类就必定不相等
命名空间
  • 每个类加载器都有自己的命名空间,命名空间由该加载器及所有的父加载器所加载的类组成
  • 在同一个命名空间中,不会出现类的完整名字相同的两个类
  • 在不同的命名空间中,有可能会出现类的完整名字相同的两个类
类加载机制的基本特征
  • 双亲委派模型:不是所有类加载都遵守这个模型,启动类加载器所加载的类型,是可能要加载用户代码的,比如JDK内部的ServiceProvider/ServiceLoader机制,用户可以在标准API框架上,提供自己的实现,JDK也需要提供些默认的参考实现,如Java中JNDI,JDBC,文件系统,Cipher等很多方面,都是利用这种机制,这种情况不会用双亲委派模型去加载,而是利用所谓的上下文加载器
  • 可见性:子类加载器可以访问父类加载器加载的类型,但是反过来是不允许的,不然,因为缺少必要的隔离,我们就没有办法利用类加载器去实现容器的逻辑
  • 单一性:由于父加载器的类型对于子加载器可见,所以父加载器中加载过的类型,就不会在子加载器中重复加载,但是注意,类加载器“邻居”间,同一类型仍然可以被加载多次,因为互相并不可见。
类加载器
  • JVM支持两种类型的类加载器,分别为引导类加载器(Bootstrap ClassLoader)和自定义类加载器(User-Defined ClassLoader)
  • 从概念上讲,自定义类加载器一般指的是程序中由开发人员自定义的一类类加载器,但是Java虚拟机规范却没有这么定义,将所有派生于抽象类ClassLoader的类加载器都划分为自定义类加载器,无论类加载器的类型如何划分,在程序中我们最常见的类加载器结构如下:
    在这里插入图片描述
  • 除了顶层的启动类加载器外,其余的类加载器都应有自己的“父类”加载器
  • 不同类加载器看似是继承(Inheritance)关系,实际上是包含关系,在下层加载器中,包含着上层加载器的引用
引导类加载器
  • 这个类加载器使用C/C++语言实现,嵌套在JVM内部
  • 它用来加载Java核心类库(JAVA_HOME/jre/lib/rt.jar或sun.boot.class.path路径下的内容)。用于提供JVM自身需要的类
  • 并不继承自java.lang.ClassLoader,没有父加载器
  • 出于安全考虑,Bootstrap启动类加载器只加载包名为java,javax,sun等开头的类
  • 加载扩展类加载器和应用程序类加载器,并指定为他们的父类加载器
  • 使用-XX:+TraceClassLoading
    在这里插入图片描述
扩展类加载器
  • Java语言编写,由sun.misc.Launcher$ExtClassLoader实现
  • 继承于ClassLoader类
  • 父类加载器为启动类加载器
  • 从java.ext.dirs系统属性所指定的目录中加载类库,或从JDK的安装目录的jre/lib/ext子目录下加载类库,如用户创建的JAR放在此目录下,也会自动由扩展类加载器加载
    在这里插入图片描述
    类加载器实验
系统类加载器(应用程序类加载器)
  • java语言编写,由sun.misc.Launcher$AppClassLoader实现
  • 派生于ClassLoader类
  • 父类加载器为扩展类加载器ExtClassLoader
  • 它负责加载环境变量classpath或系统属性java.class.path指定路径下的类库
  • 该类为程序默认的类加载器,java应用的类由它来完成加载
  • 通过ClassLoader#getSystemClassLoader()方法可以获得此类加载器
用户自定义类加载器
  • 在Java的日常应用开发中,类的加载几乎是由上述3种类加载器相互配合执行的,在必要时,我们还可以自定义类加载器,来定制类的加载方式
  • 体现Java语言的强大生命力和巨大魅力的关键因素之一便是,Java开发者可以自定义类加载器来实现类库的动态加载,加载源可以是本地的JAR包,也可以是网络上的远程资源
  • 通过类加载器可以实现非常绝妙的插件机制,这方面的实际应用安全举不胜举,例如,著名的OSGI组件框架,再如Eclipse的插件机制,类加载器为应用程序提供一种动态增加新功能的机制,这种机制无须重新打包发布应用程序就能实现
  • 同时,自定义加载器能够实现应用隔离,例如Tomcat,Spring等中间件和组件框架都在内部实现自定义的加载器,并通过自定义加载器隔离不同的组件模块,这种机制比C/C++程序要好很多,想不修改C/C++程序就能为其新增功能,几乎是不可能的,仅一个兼容性便能阻挡住所有美好设想
  • 自定义类加载器通常需要继承于ClassLoader
ClassLoader源码解析
ClassLoader与现有类加载器的关系

在这里插入图片描述

  • 除了以上虚拟机自带的加载器外,用户还可以定制自己的类加载器,Java提供了抽象类java.lang.ClassLoader,所有用户自定义的类加载器继承ClassLoader
抽象类ClassLoader主要方法
  • public final ClassLoader getParent():返回类加载器的超类加载器
  • public Class<?> loadClass(String name) throws ClassNotFoundException :加载名称为name的类,返回结果为java.lang.Class类的实例,如果找不到类,则返回ClassNotFoundException异常,该方法中的逻辑就是双亲委派模式的实现
  • protected Class<?> findClass(String name) throws ClassNotFoundException:查找二进制名称为name的类,返回结果为java.lang.Class类的实例,这是一个受保护的方法,JVM鼓励我们重写此方法,需要自定义加载器遵循双亲委派机制,该方法会在检查完父类加载器之后被loadClass()方法调用
  • 在JDK1.2之前,在自定义类加载时,总会去继承ClassLoader类并重写loadClass方法,从而实现自定义的类加载类,1.2后不再建议用户去覆盖loadClass()方法,而是建议把自定义的类加载逻辑写在findClass()方法中,从前面分析可知,findClass()方法是在loadClass()方法中被调用,当loadClass()方法中父加载器加载失败后,则会调用自己findClass()方法来完成类加载,这样就可以保证自定义类加载器也符合双亲委派模式
  • ClassLoader类中并没有实现findClass()方法的具体代码逻辑,取而代之的是抛出ClassNotFoundException异常,同时应该知道的是findClass方法通常和defineClass方法一起使用,一般情况下,在自定义加载器时,会直接覆盖ClassLoader的findClass()方法并编写加载规则,取得要加载类的字节码后转换成流,然后调用defineClass()方法生成类的Class对象
  • protected final Class<?> defineClass(String name, byte[] b, int off, int len) throws ClassFormatError:根据给定的字节数组b转换为Class实例,off和len参数表示实际Class信息在byte数组中的位置和长度,其中

待续… …

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/20481.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java学习【String类详解】

Java学习【String类详解】 String的介绍及定义方式String类型的比较String类型的查找charAt()访问字符indexOf()查找下标 转化和替换数值和字符串转化大小写的转换字符串转数组格式化替换 字符串的拆分和截取split()拆分substring()截取trim()去除两边空格 StringBuilder和Stri…

苏州金龙客车为新疆哪吒车队提供车辆交车

2024年旅游旺季提前到来、时间延长&#xff0c;新疆旅游市场有望延续去年火爆态势。 近期&#xff0c;新疆哪吒运输服务有限公司&#xff08;以下简称“哪吒车队”&#xff09;订购的最新一批10辆苏州金龙海格高端旅游大巴在苏州金龙厂区正式交付。哪吒车队负责人伍亚丽笑容满…

SpringCloud学习笔记万字整理(无广版在博客)

在此感谢黑马程序员的SpringCloud课程 所有笔记、生活分享首发于个人博客 想要获得最佳的阅读体验&#xff08;无广告且清爽&#xff09;&#xff0c;请访问本篇笔记 认识微服务 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐…

python的元组

元组与列表的区别 元组和列表非常相似。不同之处在于&#xff0c;外观上&#xff1a;列表是被 方括号 包裹起来的&#xff0c;而元组是被 圆括号 包裹起来的。本质上&#xff1a;列表里的元素可修改&#xff0c;元组里的元素是 不可以“增删改” 。 还有一个微妙的地方要注意…

MK SD NAND(贴片式SD卡)在电力AI模块中的应用案例

近期一位客户&#xff0c;在网上了解到我们SD NAND后联系到我们&#xff0c;经过一系列了解对比后&#xff0c;下单了我们的SD NAND产品。 这位客户是做电力AI模块的&#xff0c;他们的产品主要应用在电力行业。 电力AI模块是集成了人工智能技术的系统&#xff0c;专门设计用于…

微信小程序注册流程及APPID,APPSecret获取

1.注册微信小程序 注册链接&#xff1a;公众号 (qq.com) 1.1填写邮箱、密码、验证码 1.2邮箱登录点击邮件中链接激活&#xff0c;即可完成注册 1.3用户信息登记 接下来步骤&#xff0c;将用个人主题类型来进行演示 填写主体登记信息&#xff0c;使用管理员本人微信扫描二维码…

离线环境下安装NVIDIA驱动、CUDA(HUAWEI Kunpeng 920 + NVIDIA A100 + Ubuntu 20.04 LTS)

文章目录 前言 一、基础环境 1.1、处理器型号 1.2、英伟达显卡型号 1.3、操作系统 1.4、软件环境 二、取消内核自动升级 2.1、查看正在使用的内核版本 2.2、查看正在使用的内核包 2.3、禁止内核更新 三、配置本地apt源 3.1、挂载iso镜像文件 3.2、配置apt源 3.3、…

python分别保存聚类分析结果+KeyError: ‘CustomerID‘报错

如何在完成聚类分析后按聚类编号保存数据并且带上原数据所属ID # 将每个聚类的数据保存到不同的文件中 for cluster_id in range(6): # 假设共有6个聚类cluster_data data[data[cluster] cluster_id]cluster_data_with_customer_id cluster_data.copy()cluster_data_with_…

图文并茂带你理解Java的代理模式

目录 Java的代理模式1、什么是代理模式&#xff1f;2、静态代理和动态代理3、JDK动态代理的局限性4、使用CGLIB代理机制完成未实现接口的类的代理5、JDK动态代理和CGLIB动态代理对比6、JDK动态代理为什么只能代理实现接口的类&#xff1f; Java的代理模式 1、什么是代理模式&a…

vue3使用vue3-print-nb打印

打印效果 1.下载插件 Vue2.0版本安装方法 npm install vue-print-nb --saveVue3.0版本安装方法&#xff1a; npm install vue3-print-nb --save2.main.js引入 vue2引入 import Print from vue-print-nb Vue.use(Print)vue3引入 import print from vue3-print-nb // 打印…

实时监控电脑屏幕的软件是什么?三款超受欢迎的电脑监控软件

实时监控电脑屏幕的软件在现代企业管理中扮演着至关重要的角色&#xff0c;它们不仅帮助管理者实时监控员工的工作状态&#xff0c;提高工作效率&#xff0c;还通过数据分析和报告功能&#xff0c;为企业提供了优化管理流程和决策支持的依据。以下将介绍几款市面上广泛使用的实…

大模型部署_书生浦语大模型 _作业2基本demo

本节课可以让同学们实践 4 个主要内容&#xff0c;分别是&#xff1a; 1、部署 InternLM2-Chat-1.8B 模型进行智能对话 1.1安装依赖库&#xff1a; pip install huggingface-hub0.17.3 pip install transformers4.34 pip install psutil5.9.8 pip install accelerate0.24.1…

为新质生产力注入人才“活水”

21世纪最缺的是什么&#xff1f;这个梗到今天仍有现实意义&#xff0c;答案也依旧是那两个字——人才&#xff01;不过&#xff0c;随着数字化转型的深入&#xff0c;以及国家战略布局新质生产力&#xff0c;还是应该与时俱进&#xff0c;在这两个字的前面再加上一个定语&#…

Jlink驱动包

本文分享多个版本的Jlink安装驱动包。 链接: https://pan.baidu.com/s/19P2HymfPTFK2IEfAjEoSpA 提取码: cj6k 主要分享如下版本的&#xff1a; Jlink安装驱动方法&#xff1a; 点击下一步&#xff1a; 点击 同意 然后进行安装。 安装完成后点击完成 使用方法&#xff1a; …

【Linux】Linux工具——yum,vim

1.Linux 软件包管理器——yum Linux安装软件&#xff1a; 源代码安装&#xff08;不建议&#xff09;rpm安装&#xff08;类似Linux安装包&#xff0c;版本可能不兼容&#xff0c;不推荐&#xff0c;容易报错&#xff09;yum安装&#xff08;解决了安装源&#xff0c;安装版本&…

四川音盛佳云电子商务有限公司引领抖音电商新风潮

在数字化浪潮席卷全球的今天&#xff0c;电商行业已成为推动经济发展的重要力量。作为这一领域的佼佼者&#xff0c;四川音盛佳云电子商务有限公司凭借其在抖音电商服务领域的专业实力和独特视角&#xff0c;正引领着行业的新风潮&#xff0c;助力品牌实现快速增长和腾飞。 四…

使用Python发送企业微信消息

大家好&#xff0c;在本文中&#xff0c;我们将探讨如何使用 Python 发送企业微信消息。将详细说明如何通过 Python 脚本实现消息的发送。无论是希望自动化某些任务&#xff0c;还是想要快速地向团队发送实时通知&#xff0c;本文都将为您提供一站式的解决方案。 企业微信提供了…

找不到msvcr100.dll如何修复,分享几种有效的修复方法

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“找不到msvcr100.dll”。这个错误通常发生在运行某些程序时&#xff0c;系统无法找到所需的动态链接库文件。这个问题可能会给用户带来困扰&#xff0c;但是幸运的是&#xff0c;有一些简单…

汇编原理 | 二进制、跳转指令、算数运算、

一.二进制 two complement reprentation&#xff08;补码&#xff09; 二进制的运算&#xff1a; 6的二进制 0110 -6的二进制 如何表示&#xff1f; 四个bit的第一个bit表示符号&#xff1a;1负0正 -6表示为1010 解释&#xff1a; 0 0000 1 0001 -1 1111&#xff08;由 …

【Ubuntu】100 系统字体安装和更改

系统&#xff1a;Ubuntu18.04LTS 1 Why we need&#xff1f; 写这篇经验贴的原因&#xff1a; ①我需要装一下中文字体&#xff08;Qt要用&#xff09;&#xff1b; ②想调一下字体大小和默认中文字体的样式 2 装第三方字体 Step1&#xff1a;安装软件Font Manager sudo ap…