类的加载过程


 
 

第一阶段:装载阶段 →类加载器*

 
 
 

启动类加载器(又称为根加载器/引导类加载器)Boostrap ClassLoader(顶级父类,该类加载器是由 C 语言代码进行开发的,如果一个类的类加载器是 Bootstrap ClassLoader,那么该类的 getClassLoader()方法返回 null。) 启动类加载器加载的是jre和jre/lib目录下的核心库,具体路径要看你的jre安装在哪里(主要是rt.jar和部分.jar)
                                                              
扩展类加载器 Extention ClassLoader(父类是启动类加载器) 扩展类加载器加载的是jre/lib/ext目录下的扩展包
                                                              
应用类加载 Application ClassLoader(父类是扩展类加载器) 当前java工程的bin目录,也就是我们自己的Java代码编译成的class文件。(用来加载应用类路径(CLASSPATH)下的 class文件)
 
 
 
 
加载一个类:双亲(parent)委派模型
 
 
 
 

* 双亲(parent)委派模型工作过程:

从子类到父类依次查找之前是否加载过这个类,如果加载过,返回加载后产物(Class对象)。如果当前类加载器没有加载过这个,向父类继续查找。如果都没有加载过,那么从父类到子类依次尝试加载。继续失败就会抛出一个异常 ClassNotFoundException

 
 

双亲(parent)委派模型的优点:

(1)安全性,避免用户自己编写的类动态替换 Java 的一些核心类。如果不采用双亲委派模型的加载方式进行类的加载工作,那我们就可以随时使用自定义的类来动态替代 Java 核心 API 中定义的类。例如:如果黑客将“病毒代码”植入到自定义的 String 类当中,随后类加载器将自定义的 String 类加载到 JVM 上,那么此时就会对 JVM 产生意想不到“病毒攻击”。而双亲委派的这种加载方式就可以避免这种情况,因为 String 类已经在启动时就被引导类加载器进行了加载。
(2)避免类的重复加载,因为 JVM 判定两个类是否是同一个类,不仅仅根据类名是否相同进行判定,还需要判断加载该类的类加载器是否是同一个类加载器,相同的 class 文件被不同的类加载器加载得到的结果就是两个不同的类

 

装载成功的产物当前类的Class对象(保存当前类的类信息),在Java堆上保存(jdk>=1.6)

 
 
 

类加载时机:

  1. new,静态属性,静态方法调用
  2. People.class 获取Class对象
  3. 加载子类时需要提前加载父类
  4. 启动JVM,main函数所在的类需要加载

在这里插入图片描述

 
 
 

第二阶段:链接阶段(三个小阶段)

验证阶段:符合虚拟机要求,不能危害虚拟机安全(比如是否有病毒),文件格式,主次版本号,等等···

准备阶段:给静态变量开辟内存并赋类型默认值。

static int count = 10,
//count开辟四个字节,赋值0

解析阶段:解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。

  String str = “hello”;
//str 保存的是hello这个常量在磁盘上的地址 (符号引用)
//str 保存的是在JVM上的地址              (直接引用)

第三阶段:初始化阶段

                    给静态变量赋值 count = 10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值