![6880ad0ec5c44d4438dd20631b8c0325.png](https://i-blog.csdnimg.cn/blog_migrate/7846a108f55e18d069cee6d839aca0c0.png)
黑马程序员
QQ号:1967401436
传智播客旗下互联网资讯,学习资源免费分享平台
一说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()两个方法即可。
如下图:
到这, 相信大家对类加载器已经初步有一定的认识和理解了. 接下来, 我们写代码来验证一下, 代码和打印结果如下:
到这里, 代码就已经验证完毕了. 其实我们现在一直在研究的是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)。
-文末推荐-
往期技术文章:
人工智能|算法是如何从数据中学习规律的?
Java教程|keepalived实现双机热备(文末有福利)
分享点赞在看一键三连
不错过黑马程序员编程资源
![0ec07e87b7a0213aef293c71f6821f83.gif](https://i-blog.csdnimg.cn/blog_migrate/db382c0498a663da8b32a843fe90c4b3.gif)