目录
1、类加载的过程
1、加载
2、验证
3、准备
4、解析
5、初始化
6、使用
7、卸载
2. 类加载器
1. 什么是类加载器(ClassLoader)
本质是一个类,在系统运行过程中动态的将字节码文件(就是.class文件)加载到JVM中的工具
2. 类加载器的分类(3个系统自带的+用户自定义的)
从父级类到子级类分别为:BootStrapClassLoader、ExtClassLoader、AppClassLoader、自定义类加载器
1. 根加载器(BootStrapClassLoader)
用C++编写的(怪不得jdk源码中找不到,懂了),所以打印其内容将会得到null
1. 根加载器默认加载路径(在$JRE_HOME/lib下)
根加载器会默认加载系统变量 sun.boot.class.path 指定的类库(会扫描jar文件和**.class文件**),默认是 $JRE_HOME/lib下(注意这里是jre的lib下)的类库,如 rt.jar、resources.jar 等,
白话文:可以把需要加载的类的.class文件放到这个路径下
2. 扩展类加载器(ExtClassLoader)
用于加载系统所需要的扩展类库。
1. 扩展类加载器默认加载路径(在$JRE_HOME/lib/ext下)
默认加载系统变量 java.ext.dirs 指定位置下的类库,通常是 $JRE_HOME/lib/ext 目录下的类库。
3. 应用类加载器(AppClassLoader)
加载应用程序 classpath 下所有的类库。它是应用最广泛的类加载器,是我们最常打交道的类加载器,我们在程序中调用的很多 getClassLoader() 方法返回的都是它的实例。在我们自定义类加载器时如果没有特别指定,那么我们自定义的类加载器的默认父加载器也是这个应用类加载器。
白话文:AppClassLoader是应用最广、用的最多、自定义加载器的父级加载器
4. 自定义类加载器(继承ClassLoader)
如果在创建自定义类加载器时没有指定父加载器,那么默认使用 AppClassLoader 作为父加载器。
3. 系统自带的三个类加载器的区别
BootStrapClassLoader居然在代码中都找不到(亲测),说明JVM不会把这个根加载器提供给开发人员(不亏是你,怪不得叫根加载器了)
ExtClassLoader和AppClassLoader,继承了URLClassLoader最终继承ClassLoader
部分源码如下:
public class Launcher {
static class AppClassLoader extends URLClassLoader {
}
static class ExtClassLoader extends URLClassLoader {
}
}
4. 问:父加载器中的父和Java中的父类是一样吗?
Java虚拟机中的所有类加载器采用具有父子关系的树形结构进行组织(不是用extend继承的关系),在实例化每个类加载器对象时,需要为其指定一个父级类加载器对象或者默认采用应用类加载器(默认好像是AppClassLoader)为其父级类加载。
不一样,父加载器中的《父》是父级类而不是父类(哈哈,是不是看不懂了,父级类就理解为流程图一样的结构,有先后顺序)
原文链接:https://blog.csdn.net/weixin_45325628/article/details/123029952
3、类加载器的双亲委派机制(加载类时候的机制)
如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。
白话文:类加载器加载一个类的时候,会先去问问父加载器能不能加载,如果不行,那就自己去加载
1. 问:为什么要用双亲委派?
为了安全,像一些系统相关的基础类,必须由根加载器加载(沙箱安全机制,防止核心API库被随意篡改)
为了防止类被重复创建,保证被加载类的唯一性
2、全盘负责委托机制
当一个ClassLoder装载一个类时,除非指定的使用另外一个ClassLoder,该类所依赖及引用的类也由这个ClassLoder载入。
4、JVM虚拟机
栈的内部结构
垃圾回收机制
年轻代老年代
STW stop the word