bootstrap 数据加载中提示_Java | 类加载器的工作原理

6880ad0ec5c44d4438dd20631b8c0325.png

黑马程序员

QQ号:1967401436

传智播客旗下互联网资讯,学习资源免费分享平台

81a0774270ceaef2c0f627793294e81b.gif

一说Java代码的执行, 接触过Java代码的同学肯定会想到: 编写, 编译, 运行这三个阶段. 其中:

编写: 是在后缀名为.java的文件中, 根据Java语法规则编写源代码。

编译: 是将.java文件(源代码文件)编译成.class文件(字节码文件)。

运行: 是通过JVM来执行.class字节码文件。

大白话解释: .Java文件是程序员能看懂, 但是计算机看不懂的文件. 需要先把它转换成.class文件, 计算机才能识别, 从而来执行。虽然这三个阶段都可以通过IDE实现, 但是好多人容易忽略一个细节, 那就是: 在JVM执行.class字节码文件之前, 需要先通过”类加载器”将该字节码文件加载到内存中, 而这个过程, 就是我们要详聊的话题。

本文会从以下3点来介绍”Java中的”类加载器:

1.类加载器的概述;

2.类加载器的分类;

3.类加载机制。

类加载器的概述

首先, 我们先来聊下类加载器的概述, 类加载器(ClassLoader)是负责加载类的对象的, 也就是将.class字节码文件加载到JVM内存中的. 那它什么时候才会去加载.class字节码文件呢? 答案是: 当Java程序第一次使用某个类中的内容, 而该类的字节码文件在内存中不存在时, 类加载器就会去加载该类的字节码文件。

俗话说”渡人先渡己”, 要想成为别人的榜样, 帮助别人. 首先要做好自己. 生活中如此, 类加载器也一样. 要想加载我们自定义的类, 类加载器必须先完成”自加载”的过程. 聊到这, 不得不提的就是”类加载器的分类”了。

类加载器的分类

Java中的类加载器主要分为以下四类:

1.根类加载器(BootStrapClassLoader), 主要负责加载jre/lib/rt.jar相关的字节码文件的。

2.扩展类加载器(ExtensionClassLoader), 主要负载加载 jre/lib/ext/*.jar 这些jar包的. 该类加载器在JDK1.9的时候更名为: Platform Class Loader, 其父类加载器为: null。

3.应用程序类加载器(ApplicationClassLoader), 主要负责加载用户自定义的类以及classpath环境变量所配置的jar包的. 该类加载器在JDK1.9的时候更名为: System ClassLoader, 其父类加载器为: ExtensionClassLoader。

4.自定义类加载器(UserClassLoader), 负责加载程序员指定的特殊目录下的字节码文件的. 大多数情况下, 自定义类加载器只需要继承ClassLoader这个抽象类, 重写findClass()和loadClass()两个方法即可。

如下图:

ef6a5b5f2b3592fc5f42a2b338cd261b.png

到这, 相信大家对类加载器已经初步有一定的认识和理解了. 接下来, 我们写代码来验证一下, 代码和打印结果如下:

15536e2a56d0c1542ba6f49735985375.png

到这里, 代码就已经验证完毕了. 其实我们现在一直在研究的是JVM类加载机制的"加载循序", 现在, 我们来研究下它的"检查顺序", 请你思考, 假设: D:compile, ext*.jar, rt.jar三类中都有 A.class, 那么A.class是否会被加载3次, 如果不会, 它的加载顺序是什么样的?

答案是: 不会被加载3次, 并最终会由BootStrapClassLoader来加载A.class。

原因是因为, APPClassLoader类加载器(以下简称: app)加载之前, 会先询问ExtClassLoader类加载器(以下简称: ext)是否加载. 如果ext加载, app就不加载了, 反之则app加载. 同样, ext在加载之前, 也会询问BootStrapClassLoader类加载器(以下简称: bootstrap)是否加载, 如果bootstrap加载, 则ext就不加载了, 反之, 则ext加载. 这也是: JVM类加载机制的”双亲委派机制”。

类加载器机制

最后, 我们再来聊一聊”类加载机制”, 在JVM中类加载机制主要有3种:

1.全盘加载. 顾名思义, 就是当某一个类加载器加载某个.class文件时, 默认也会连同该文件所依赖的.class一起加载(除非显示声明通过某个指定的类加载器加载)。

2.缓存机制. 即所有类加载器已经加载过的.class文件都会被保存到缓存中, 下次使用该.class文件时, JVM会优先从缓存中查找, 如果没有, 才会去加载指定的字节码文件, 这也是为什么当字节码文件变化后, 需要重启JVM后才能看到修改效果的原因。

3.双亲委派. 大白话解释, 儿子(App)要星星, 他自己实现不了, 就找他老爹(Ext)要, 他老爹能实现的话就给他了, 实现不了, 就找他爷爷(BootStrap)要, 说: 你孙子要天上的星星. 他爷爷如果能实现就给了, 如果也实现不了, 就会告诉他爹(Ext), 让你儿子(App)自己实现吧. 这种情况有点极端, 属于谁都没有加载, 则程序报错, 会抛出异常。

总结: 类加载器自上而下检查(App --> Ext --> BootStrap), 自下而上加载(BootStrap --> Ext --> App)。

-文末推荐-

d4a3f573417267cf718c6c8d4fa3933f.png

往期技术文章:

  • 人工智能|算法是如何从数据中学习规律的?

  • Java教程|keepalived实现双机热备(文末有福利)

分享点赞在看一键三连

不错过黑马程序员编程资源

98c6b9d0d4d284df982a0ed044077006.gif

我就知道你会 “在看” 0ec07e87b7a0213aef293c71f6821f83.gif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值