网站首页 > java教程 正文
一说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).
猜你喜欢
- 2024-10-06 一文搞定java.lang.Class.isInstance和instanceof的区别
- 2024-10-06 如何使用Java 文件系统 File类?(java files类)
- 2024-10-06 Spring问题之提示文件不存在处理it does not exist
- 2024-10-06 java常见问题(java常见问题及答案)
- 2024-10-06 「Java」常用的文件操作(java 文件处理)
- 2024-10-06 JAVA中的文件操作2-如何读写文件(java高并发读写文件)
- 2024-10-06 bitmap算法:如何在20亿个非负整数中如何判断一个数是否存在?
- 2024-10-06 Java 如何验证文件名的有效性?(java判断文件名包含字符串)
- 2024-10-06 java中读取properties文件最简单的方法
- 2024-10-06 五十六、探析Java文件过滤技术与高级文件检索方法
你 发表评论:
欢迎- 最近发表
-
- 你真的会用 Java 中的线程池吗?多个企业级线程池工具类封装实践
- 线程池的实现原理、优点与风险、以及四种线程池实现
- Java线程池ThreadPoolExecutor实现原理剖析
- 深入分析线程池的实现原理(线程池是干嘛的)
- 一文搞懂JAVA线程池工作原理(java线程池的工作流程)
- Java线程池的工作原理(java线程池的实现原理)
- 5分钟读懂C#中TcpClient、TcpListener和Socket三个类的角色
- JVM对象的创建过程(jvm运行过程中创建的对象一般存放在方法区)
- 对象组成与Java内存模型JMM分析(java对象在内存中存储的结构)
- JVM对象内存分配详细过程(栈上分配->TLAB->老年代->Eden区)
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)