一、类加载
类加载的流程:
1.加载:根据类名找到文件,读取文件,解析架构,把内容放到内存中,并构造出类的对象
2.链接:如果该类依赖了一些其他类,链接过程就是把依赖内容进行引入
3.初始化:初始化静态成员,并执行代码块
二、什么时候会触发某个类的加载?
a)构造该类的实例
b)调用该类的静态属性或者方法
c)使用子类时会触发父类的加载
举例:分析如下代码的执行顺序。
class AA{
public AA(){
System.out.println("AA.构造");
}
{
System.out.println("AA.{}");
}
static {
System.out.println("AA.static{}");
}
}
class BB extends AA{
//构造方法
public BB(){
System.out.println("BB.构造");
}
//普通代码块
{
System.out.println("BB.{}");
}
//静态代码块
static {
System.out.println("BB.static{}");
}
}
public class Demo2 extends BB{
public static void main(String[] args) {
System.out.println("开始");
new BB();
new BB();
System.out.println("结束");
}
}
————————————————
版权声明:本文为CSDN博主「水果篮子~」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_42803467/article/details/120616543
1.代码先从main方法执行。main 是Demo2这个类的静态方法,就会触发Demo2的类加载。
2.BB 是 Demo2的父类,在加载Demo2之前,会先加载BB
3.AA 又是BB 的父类,加载BB 之前又会先加载AA
综上加载AA-》加载BB-》加载Demo2-》执行main方法
4.加载AA 调用其中的静态代码块
5.加载BB,调用BB 的静态代码块
6.Demo2没有静态代码块了,执行main方法内容
7.new BB(),构造BB 的实例会先构造AA的实例,需要先构造AA 中的代码块和构造方法
8.第二次构造BB 同 7
9.最后打印结束
【注意】代码块的执行顺序为:先执行静态代码块,接着是普通代码块,最后是构造方法
以上代码执行的结果:
AA.static{}
BB.static{}
开始
AA.{}
AA.构造
BB.{}
BB.构造
AA.{}
AA.构造
BB.{}
BB.构造
结束
三、类加载器有哪些?
1)BootstrapClassLoader 加载标准库中的类,String,ArrayList
2)ExtensionClassLoader 加载一个特殊目录中的类
- ApplicationClassLoader 加载应用程序自己写的类
代码示例:
package interview;
/**
* @program: java16_blogdemo
* @description
* @author: wenwen
* @create: 2021-10-04 19:07
**/
import sun.net.spi.nameservice.dns.DNSNameService;
public class Demo3 {
public static void main(String[] args) {
ClassLoader classLoader1 = Demo3.class.getClassLoader();
System.out.println(classLoader1);
ClassLoader classLoader2 = String.class.getClassLoader();
System.out.println(classLoader2);
ClassLoader classLoader3 = DNSNameService.class.getClassLoader();
System.out.println(classLoader3);
}
}
四、什么是双亲委派模型?
双亲委派模型描述的是:在类加载中,根据类名找到类的.class文件的查找过程。
三个类加载器之间存在“父子关系”(和继承无关),类加载器中有一个parent 属性,指向了自己的父亲
以加载String 类为例看双亲委派模型
给一个类名:java.lang.String,让类加载器通过类名找到对应的 class 文件
1.先从AppClassLoader 开始
2.AppClassLoader 不会立刻查找,而是先把类名交给它的父亲,先让父亲查找
3.ExtClassLoader 也不会立刻进行查找,而是把类名又交给它的父亲
4.BootstrapClassLoader 拿到类名之后,只能自己亲自查找.rt.jar, 如果找到了,就直接加载类即可,如果未找到,再把这个类名交还ExtClassLoader 来查找
5.ExtClassLoader 再根据类名在ext 目录中查找,如果找到就加载,如果没找到,就把这个类名再还给AppClassLoader进行加载
6.AppClassLoader 再去CLASS_PATH 环境变量,-cp指定的目录,当前目录中再去查找,如果找到了,就进行加载,如果没找到,就抛出一个ClassNotFoundException
双亲委派模型目的就是:尽量让标准库的类优先被加载,例如,在代码中创建一个java.lang.String这样的类,名字和标准库的String类相同,此时优先加载标准库的String
注意:可以违背双亲委派模型,只是标准库中的三个类加载器都要遵守,其他的类加载器不太需要遵守, 例如Tomcat 中的类加载器就没有遵守(要从webapps 目录中加载指定的webapp 的类)
————————————————
版权声明:本文为CSDN博主「水果篮子~」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_42803467/article/details/120616543