一、类加载
1.1、在java代码中,类型的加载,连接,初始化过程都是在程序运行期间完成的。
图示:
1.2、类型的加载——这里的类型是指的什么?
答:类型就是指的我们Java源代码通过编译后的class文件。
1.3、类型的来源有哪些?
(1)本地磁盘
(2)网络下载,class文件
(3)war,jar下加载,class文件
(4)从专门的数据库中读取,class文件(少见)
(5)将java源文件动态编译成class文件
1)典型的就是动态代理,通过运行期生成class文件
2)我们的jsp会被转换成servlet,而我们的serlvet是一个java文件,会被编译成class文件
1.4、通过什么来进行加载?(类加载器)
1.5、类加载的分类以及各种加载职责以及层级结构
(1)系统级别
1)启动类加载器
2)扩展类加载器
3)系统类加载器(App类加载器)
(2)用户级别的
自定义类加载器(继承我们的ClassLoader)
(3)层级结构
二、类加载器加载我们的Class的时候遵循我们的双亲委派模型
在双亲委派机制中,各个加载器按照父子关系形成树型结构,除了根加载器以外,每一个加载器有且只有一个父加载器
1、源码分析:
复制代码
1 protected Class<?> loadClass(String name, boolean resolve)
2 throws ClassNotFoundException
3 {
4 synchronized (getClassLoadingLock(name)) {
5 //检查当前的class对象是否被加载过,被加载过就返回
6 Class<?> c = findLoadedClass(name);
7 if (c == null) {
8 long t0 = System.nanoTime();
9 try {
10 //判断当前的classLoader是否有父类
11 //若存在父类
12 if (parent != null) {
13 //调用父类的loadClass
14 c = parent.loadClass(name, false);
15 } else {//不存在父类,表示当前的classLoader是extClassLoader
16 //那么就会调用启动类判断是否加载过
17 c = findBootstrapClassOrNull(name);
18 }
19 } catch (ClassNotFoundException e) {
20 // ClassNotFoundException thrown if class not found
21 // from the non‐null parent class loader
22 }
23 //到目标位置,app ext boot都没有去加载过
24 if (c == null) {
25 // If still not found, then invoke findClass in order
26 // to find the class.
27 long t1 = System.nanoTime();
28 //委托我们的子类的classLoader去找
29 c = findClass(name);
30
31 // this is the defining class loader; record the stats
32 sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 ‐ t0);
33 sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
34 sun.misc.PerfCounter.getFindClasses().increment();
35 }
36 }
37 if (resolve) {
38 resolveClass©;
39 }
40 return c;
41 }
42 }
复制代码
2、双亲委派模型加载的流程图
3、类加载器的双亲委派模型的好处:
总所周知:java.lang.object类是所有类的父类,所以我们程序在运行期间会把java.lang.object类加载到内存中,假如java.lang.object类能够被我们自定义类加载器去加载的话,那么jvm中就会存在多份Object的Class对象,而且这些Class对象是不兼容的。
所以双亲委派模型可以保证java核心类库下的类型的安全。
借助双亲委派模型,我们java核心类库的类必须是由我们的启动类加载器加载的,这样可以确保我们核心类库只会在jvm中存在一份这就不会给自定义类加载器去加载我们核心类库的类。
根据我们的演示案例,一个class可以由多个类加载器去加载,同事可以在jvm内存中存在多个不同版本的Class对象,这些对象是不兼容的。
4、如何手写一个自定义类加载器(根据ClassLoader的doc文档)
(1)我们自定义类加载器必须要继承ClassLoader
(2)我们必须要findClass(String name)方法
复制代码
1 /**
2 * Finds the class with the specified binary name.
3 * This method should be overridden by class