Java中的类加载器ClassLoader
目录
- 类加载机制的层次结构
- 启动 `Bootstrap` 类加载器
- 扩展 `Extension` 类加载器
- 系统 `System` 类加载器
- 双亲委派模式
- 双亲委派模式工作原理
- 双亲委派模式优势
- 类加载器之间的关系
- 类与类加载器
- 类与类加载器
- `class` 文件的显式加载与隐式加载
类加载机制的层次结构
每个编写的 .java
拓展名类文件都存储着需要执行的程序逻辑,这些 .java
文件经过 Java
编译器编译成拓展名为 .class
的文件,.class
文件中保存着 Java
代码经转换后的虚拟机指令,当需要使用某个类时,虚拟机将会加载它的 .class
文件,并创建对应的 class
对象,将 class
文件加载到虚拟机的内存,这个过程称为类加载,这里我们需要了解一下类加载的过程,如下
- 加载:类加载过程的第一个阶段,通过一个类的完全限定查找此类字节码文件,并利用字节码文件创建一个
Class
对象 - 验证:目的在于确保
Class
文件的字节流中包含信息符合当前虚拟机要求,不会危害虚拟机自身安全。主要包括四种验证,文件格式验证,元数据验证,字节码验证,符号引用验证 - 准备:为类变量(即
static
修饰的字段变量)分配内存并且设置该类变量的初始值即0
(如static int i = 5;
这里只将i
初始化为0
,至于5
的值将在初始化时赋值),这里不包含用final
修饰的static
,因为final
在编译的时候就会分配了,注意这里不会为实例变量分配初始化,类变量会分配在方法区中,而实例变量是会随着对象一起分配到Java
堆中 - 解析:主要将常量池中的符号引用替换为直接引用的过程。符号引用就是一组符号来描述目标,可以是任何字面量,而直接引用就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄。有类或接口的解析,字段解析,类方法解析,接口方法解析(这里涉及到字节码变量的引用
- 初始化:类加载最后阶段,若该类具有超类,则对其进行初始化,执行静态初始化器和静态初始化成员变量(如前面只初始化了默认值的
static
变量将会在这个阶段赋值,成员变量也将被初始化)
这便是类加载的 5
个过程,而类加载器的任务是根据一个类的全限定名来读取此类的二进制字节流到 JVM
中,然后转换为一个与目标类对应的 java.lang.Class
对象实例。在虚拟机提供了 3
种类加载器,引导(Bootstrap
)类加载器、扩展(Extension
)类加载器、系统(System
)类加载器(也称应用类加载器),下面分别介绍
启动 Bootstrap
类加载器
启动类加载器主要加载的是 JVM
自身需要的类,这个类加载使用 C++
语言实现的,是虚拟机自身的一部分,它负责将 <JAVA_HOME>/lib
路径下的核心类库或 -Xbootclasspath
参数指定的路径下的 jar
包加载到内存中,注意必由于虚拟机是按照文件名识别加载 jar
包的,如 rt.jar
,如果文件名不被虚拟机识别,即使把 jar
包丢到 lib
目录下也是没有作用的(出于安全考虑,Bootstrap
启动类加载器只加载包名为 java
、javax
、sun
等开头的类)
扩展 Extension
类加载器
扩展类加载器是指 Sun
公司实现的 sun.misc.Launcher$ExtClassLoader
类,由 Java
语言实现的,是 Launcher
的静态内部类,它负责加载 <JAVA_HOME>/lib/ext
目录下或者由系统变量 -Djava.ext.dir
指定位路径中的类库,开发者可以直接使用标准扩展类加载器
系统 System
类加载器
也称应用程序加载器是指 Sun
公司实现的 sun.misc.Launcher$AppClassLoader
。它负责加载系统类路径 java -classpath
或 -D java.class.path
指定路径下的类库,也就是我们经常用到的 classpath
路径,开发者可以直接使用系统类加载器,一般情况下该类加载是程序中默认的类加载器,通过 ClassLoader#getSystemClassLoader()
方法可以获取到该类加载器
在日常开发中,类的加载几乎是由上述 3
种类加载器相互配合执行的,在必要时,我们还可以自定义类加载器,需要注意的是,Java
虚拟机对 class
文件采用的是按需加载的方式,也就是说当需要使用该类时才会将它的 class
文件加载到内存生成 class
对象,而且加载某个类的 class
文件时,Java
虚拟机采用的是双亲委派模式即把请求交由父类处理,它一种任务委派模式,下面我们进一步了解它
双亲委派模式
双亲委派模式工作原理
双亲委派模式要求:除了顶层的 Bootstrap
类加载器外,其余的类加载器都应当有自己的父类加载器。请注意双亲委派模式中的父子关系并非通常所说的类继承关系,而是采用组合关系来复用父类加载器的相关代码,类加载器间的关系如下
双亲委派模式是在 Java 1.2
后引入的,其工作原理的是:如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的Bootstrap
类加载器,如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是双亲委派模式,即每个儿子都很懒,每次有活就丢给父亲去干,直到父亲说这活我也干不了时,儿子才自己想办法去完成,这不就是传说中的实力坑爹啊?那么采用这种模式有啥用呢?
双亲委派模式优势
采用双亲委派模式的是好处
Java
类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关可以避免类的重复加载,当父亲已经加载了该类时,就没有必要子类加载器再加载一次- 其次是考虑到安全因素,
Java
核心API
中定义类型不会被随意替换,假设通过网络传递一个名为java.lang.Integer
的类,通过双亲委托模式传递到Bootstrap
类加载器,而Bootstrap
类加载器在核心Java API
发现这个名字的类,发现该类已被加载,并不会重新加载网络传递的过来的java.lang.Integer
,而直接返回已加载过的Integer.class
,这样便可以防止核心API
库被随意篡改
可能你会想,如果我们在 classpath
路径下自定义一个名为 java.lang.SingleInterge
类(该类是胡编的)呢?该类并不存在 java.lang
中,经过双亲委托模式,传递到 Bootstrap
类加载器中,由于父类加载器路径下并没有该类,所以不会加载,将反向委托给子类加载器加载,最终会通过系统类加载器加载该类。但是这样做是不允许,因为 java.lang
是核心 API
包,需要访问权限,强制加载将会报出如下异常
java.lang.SecurityException: Prohibited package name: java.lang
所以无论如何都无法加载成功的。下面了解几个 Java
中定义的类加载器及其双亲委派模式的实现,它们类图关系如下
从图可以看出顶层的类加载器是 ClassLoader
类,它是一个抽象类,其后所有的类加载器都继承自 ClassLoader
(不包括 Bootstrap
类加载器)
类加载器之间的关系
Bootstrap
类加载器,由C++
实现,没有父类- 拓展
Extension
类加载器(ExtClassLoader
),由Java
语言实现,父类加载器为null
System
类加载器(AppClassLoader
),由Java
语言实现,父类加载器为ExtClassLoader
- 自定义类加载器,父类加载器肯定为
AppClassLoader
类与类加载器
类与类加载器
在 JVM
中表示两个 class
对象是否为同一个类对象,存在两个必要条件
- 类的完整类名必须一致,包括包名
- 加载这个类的
ClassLoader
(指ClassLoader
实例对象)必须相同
也就是说,在 JVM
中,即使这个两个类对象(class
对象)来源同一个 Class
文件,被同一个虚拟机所加载,但只要加载它们的 ClassLoader
实例对象不同,那么这两个类对象也是不相等的,这是因为不同的 ClassLoader
实例对象都拥有不同的独立的类名称空间,所以加载的 class
对象也会存在不同的类名空间中
class
文件的显式加载与隐式加载
所谓 class
文件的显式加载与隐式加载的方式:JVM
加载 class
文件到内存的方式。
- 显式加载:在代码中通过调用
ClassLoader
加载class
对象,如直接使用Class.forName(name)
或this.getClass().getClassLoader().loadClass()
加载class
对象 - 隐式加载则是不直接在代码中调用
ClassLoader
的方法加载class
对象,而是通过虚拟机自动加载到内存中,如在加载某个类的class
文件时,该类的class
文件中引用了另外一个类的对象,此时额外引用的类将通过JVM
自动加载到内存中
转载:https://blog.csdn.net/javazejian/article/details/73413292
Java中的类加载器ClassLoader相关推荐
- Java虚拟机学习 - 类加载器(ClassLoader)
类加载器 类加载器(ClassLoader)用来加载 class字节码到 Java 虚拟机中.一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源文件在经过 Javac之后就被转换成 ...
- java中的类加载器有,Java自定义的类加载器,java自定义加载,在java中类加载器有以...
Java自定义的类加载器,java自定义加载,在java中类加载器有以 在java中类加载器有以下几种java虚拟机自带的加载器 1)根类加载器(Bootstrap,c++实现)2)扩展类加载器(Ex ...
- 通过这一篇文章,可以把Java中的类加载器了解的七七八八了
对于每个开发人员来说,java.lang.ClassNotFoundExcetpion这个异常几乎都遇到过,而追求其该异常的来源的话,就免不了谈一谈Java的类加载器了.本文就基于启动类加载器.扩展类 ...
- Java中的类加载器(ClassLoader)及类的加载机制
类加载器就是用来将class文件加载到内存中的一个java类! 系统默认有三个类加载器! ①BootStrap:这不是java类,是java虚拟机在启动的时候加载的第一个类,这个加载器用来加载核心类, ...
- 随笔18 java中的类加载器
类的加载是由类加载器完成的,类加载器包括:根加载器( BootStrap ).扩展加载器( Extension ).系统加载器( System )和用户自定义类加载器( java.lang.Class ...
- java.lang包—类加载器ClassLoader类
注意: 类加载器的知识与JVM内存模型紧密相连,要学好这块的知识,一定要掌握JVM的内存模型. 关于JVM内存模型,推荐阅读:JVM-内存模型JMM 目录 一.什么是ClassLoader? 二.类加 ...
- 【Android 逆向】类加载器 ClassLoader ( Android 的八种类加载器 | ClassLoader | BaseDexClassLoader | DexClassLoader )
文章目录 一.Android 类加载器 1.ClassLoader 抽象类 2.BootClassLoader 3.BaseDexClassLoader 4.PathClassLoader 5.Dex ...
- jdk类加载器执行步骤_[JDK 11] jcmd中的类加载器层次结构详细信息
jdk类加载器执行步骤 自从在JavaOne 2012上听说 jcmd以来,我就一直是命令行诊断工具jcmd的 粉丝 . 从那时起,我已经广泛使用了此工具,并多次在此博客中发布过此工具: jcmd:一 ...
- [JDK 11] jcmd中的类加载器层次结构详细信息
自从在JavaOne 2012上听说 jcmd以来,我就一直是命令行诊断工具jcmd的 粉丝 . 从那时起,我已广泛使用此工具,并多次在此博客中发布过此工具: jcmd:一个可以全部统治的JDK命令行 ...
- java类加载器_类加载器ClassLoader
上篇文章说到,Class类可以通过一个类的全限定名去加载类,那么底层是如何去加载的呢?这就是我们今天要聊的类加载器ClassLoader,其可以通过一个类的全限定名来获取描述此类的二进制字节流,也即是 ...
最新文章
- 【PHP开发规范】继承与扩展:PSR-2 编码风格规范
- CTFshow 爆破 web26
- wxWidgets:wxAuiNotebook类用法
- java判断类型_Java中类型判断的几种方式 - 码农小胖哥 - 博客园
- HTML列表标签,大牛最佳总结
- [算法]-排序算法之希尔排序
- Nginx 的线程池与性能剖析【转载】
- MVC中Model BLL层Model模型互转
- 再谈正态分布或高斯函数
- 《21天学通C语言》总结(2)
- JAVA微信小程序论坛系统毕业设计 开题报告
- C#中的IntPtr
- 正则表达式在线测试 | 菜鸟工具
- xlsx表格怎么筛选重复数据_在Excel中怎样筛选以及删除重复的数据呢?
- 高仿精仿微信客户端源码完整版
- 基于vue和nodejs毕业设计电影购票微信小程序影院
- 单词学习-长久的过程
- 太傻生活原则是:“无需选择,理解一切,接受一切”--《太傻十日谈》读后感
- (C++学习笔记七)运算符重载
- Google创新机器
热门文章
- TensorFlow by Google神经网络深度学习的 Hello World Machine Learning Foundations: Ep #1 - What is ML?
- WKWebView终极指南
- html扩展名用于保存清单文件,html5 – HTML 5缓存清单是否也适用于ajax请求?
- java积分签到功能_对于签到功能的一点理解
- 609. 在系统中查找重复文件
- mysql导入.sql文件
- java.nio.file中的Paths类
- Raider:Web身份认证测试框架
- MySQL蜜罐在护网中提取攻击者微信ID
- mysql登录出现1045错误