Java的类加载过程

类的加载过程可分为五个阶段:1.加载2.链接3.初始化阶段4.使用5.卸载

1.加载
将编译生成的class文件通过类加载器动态加载到Java虚拟机上
类加载器:
(1)启动类加载器:BootstrapClassLoader

用来加载Java的核心库,是用C++实现的
主要加载 JAVA_HOME/jre/lib 里的jar 包, 该目录下的所有 jar 包都是运行 Java虚拟机 时所必需的 jar 包。
注意: 类加载器其实自身也是一个 Java 类, 因此,自身类加载器需要被其他类加载器进行加载后方可使用, 显然必须有一个类加载器的顶级父类(也就是 BootstrapClassLoader

(2)扩展类加载器:ExtentionsClassLoader

它用来加载Java的扩展类库(主要是Java系统类的继承类和实现类)ExtClassLoader 主要加载 Java 核心扩展类, 即 JAVA_HOME/jre/ext 目录下的 jar 文件。

(3)应用类加载器:ApplicationClassLoader

AppClassLoader 主要加载的是开发者在应用程序中编写的类, 即 CLASSPATH 路径下所有的 jar 文件。

Java中类的唯一性由类和类加载器共同维护。
三个加载器各自完成自己的工作,但它们是如何协调工作呢?哪一个类该由哪个类加载器完成呢?为了解决这个问题,Java采用了委托模型机制。
双亲委派模型
从子类到父类依次查找当前类加载器之前是否加载过这个类,如果类没有被加载过,则由父类到子类依次尝试加载。
工作过程:
(1) 当前类加载器从自己已经加载的类中查询是否此类已经加载, 如果已经加载则返回原来已经加载的类。
(2) 如果没有找到, 就去委托父类加载器去加载。 父类加载器也会采用同样的策略, 查看自己已经加载过的类中是否包含这个类, 有就返回, 没有就委托其父类去加载, 直到委托到启动类加载器为止。 因为如果父类加载器为空了, 就代表使用启动类加载器作为父加载器去加载该类。
(3) 如果启动类加载器加载失败, 就会使用扩展类加载器来尝试加载, 继续失败则会使用 AppClassLoader 来加载, 继续失败就会抛出一个异常 ClassNotFoundException。
优点:
(1) 安全性, 避免用户自己编写的类动态替换 Java 的一些核心类。 如果不采用双亲委派模型的加载方式进行类的加载工作, 那我们就可以随时使用自定义的类来动态替代 Java 核心 API 中定义的类。 例如: 如果黑客将“病毒代码” 植入到自定义的 String 类当中, 随后类加载器将自定义的 String 类加载到 JVM 上, 那么此时就会对 JVM 产生意想不到“病毒攻击”。 而双亲委派的这种加载方式就可以避免这种情况, 因为 String 类已经在启动时就被引导类加载器进行了加载。
(2) 避免类的重复加载, 因为 JVM 判定两个类是否是同一个类, 不仅仅根据类名是否相同进行判定, 还需要判断加载该类的类加载器是否是同一个类加载器, 相同的 class 文件被不同的类加载器加载得到的结果就是两个不同的类。

2.链接
①验证
验证是链接阶段的第一步,这一阶段的目的是为了确保class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全
②准备
给静态变量在方法区上开辟内存同时给予其类型的默认值,如int类型为0,引用数据类型为null
③解析
Java虚拟机将常量池中的符号引用替换为直接引用

3.初始化
给static修饰的类变量赋值

4.使用
在new对象的时候,类的加载的顺序为:
父类静态变量、父类静态块、子类静态变量、子类静态块、父类实例变量、父类实例块、父类构造方法、子类实例变量、子类实例块、子类构造方法
5.卸载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值