美文网首页
第二十四章、Java类加载过程

第二十四章、Java类加载过程

作者: 小母牛不生产奶 | 来源:发表于2018-11-14 20:45 被阅读8次

类从被加载到JVM中开始,到卸载为止,整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段。

其中类加载过程包括加载、链接 和初始化五个阶段.

加载阶段:

java将字节码数据从不同的数据有读取到JVM中,并映射为JVM认可的数据结构(Class对象),这里的数据源可能是各种各样的形态,如jar文件、class文件、甚至是网络数据源等;如果输入数据不是ClassFile的结构,则会抛出ClassFormatError。

加载阶段是用户参与的阶段,我们可以自定义类加载器,去实现自己的类加载过程。

链接(Linkling)阶段:

这是核心的步骤,简单说是把原始的类定义信息平滑地转入JVM运行的过程中。这里可进一步细分为三个步骤:

验证(Verfication),这是虚拟机安全的重要保障,JVM需要核验直接信息是符合Java虚拟机规范的,否则就被认为是VerifyError,这样就防止了恶意信息或者不合规的信息危害JVM的运行,验证阶段由可能触发更多class的加载。

准备,创建类或接口中的静态变量,并初始化静态变量的初始值。但这里的“初始化”和下面的显式初始化阶段是由区别的,侧重点在于分配所需的内存空间,不会去执行更进一步的JVM指令。

解析,在这一部会见常量池中的符号引用替换为直接引用。

初始化阶段:

这一步真正去执行类初始化的代码逻辑,包括静态字段赋值的动作,以及执行类定义中的静态初始块内的逻辑,包括静态赋值的动作,以及执行内定义中的静态初始块内的逻辑,编译器在编译阶段就会把这部分逻辑整理好,父类型的初始化逻辑优先于当前类型的逻辑。

再来谈谈双亲委派模型,简单说就是当类加载器(Class-Loader)试图加载某个类型的时候,除非父加载器找不到相应的类型,否则尽量将这个任务代理给当前加载器的父加载器去做。使用委派模型的目的是避免重复加载java类型。


类加载器的结构

1、启动类加载器(Bootstrap Class-Loader),加载jre/lib 下面的jar文件,如rt.jar。它是个超级公民,即使是在开启了Security Manager的时候,JDK仍赋予了它加载的程序AllPermission。

2、扩展类加载器(Extension or Ext Class-Loader),负责加载我们放到jre/lib/ext/目录下面的jar包,这就是所谓的extension机制。该目录也可以通过设置“java.ext.dirs”来覆盖。

3、应用类加载器(Application or App Class-Loader),就是加载classpath的内容,这里有个容易混淆的概念,系统(System)类加载器,通常来说,其默认就是JDK内建的应用类加载器,但是它同样是可能修改的。

双亲委派模型

类加载机制的三个基本特征

1、双亲委派模型,但不是所有类加载都遵循这个模型,有的时候,启动类加载器所加载的类型,是可能要加载用户代码的,比如JDK内部的ServiceProvider/ServiceLoader机制,用户可以在标准API框架上,提供自己的实现,JDK也需要提供些默认的参考实现。例如,在Java中JNDI、JDBC、文件系统、Cipher等很多方面,都是利用的这种机制,这种情况就不会用双亲委派模型去加载,而是利用所谓的上下文加载器。

2、可见性,子类加载器可以访问父加载器加载的类型,但是反过来是不允许的,不然,因为缺少必要的隔离,就没有办法利用类加载器去实现容器的逻辑。

3、单一性,由于父加载器的类型对于子加载器是可见的,所以父加载器中加载过的类型,就不会在子加载器中重复加载。但是注意,类加载器“邻居”间,同一类型仍然可以被加载多次,因为互相并不可见。

相关文章

网友评论

      本文标题:第二十四章、Java类加载过程

      本文链接:https://www.haomeiwen.com/subject/drndfqtx.html