关于java:类加载机制和双亲委派模型

4次阅读

共计 1704 个字符,预计需要花费 5 分钟才能阅读完成。

什么是类的加载

类的加载指的是将类的.class 文件中的二进制数据读入到内存中,类的加载的最终产品是位于堆区中的 Class 对象,Class 对象封装了类在办法区内的数据结构。

类的生命周期

其中类加载的过程包含了加载、验证、筹备、解析、初始化五个阶段。在这五个阶段中,加载、验证、筹备和初始化这四个阶段产生的程序是确定的,而解析阶段则不肯定,它在某些状况下能够在初始化阶段之后开始,这是为了反对 Java 语言的运行时绑定(也成为动静绑定或早期绑定)。另外留神这里的几个阶段是按程序开始,而不是按程序进行或实现,因为这些阶段通常都是相互穿插地混合进行的,通常在一个阶段执行的过程中调用或激活另一个阶段。

加载

加载阶段是类加载过程的第一个阶段。在这个阶段,JVM 的次要目标是将字节码从各个地位(网络、磁盘等)转化为二进制字节流加载到内存中,接着会为这个类在 JVM 的办法区创立一个对应的 Class 对象,这个 Class 对象就是这个类各种数据的拜访入口。

验证

当 JVM 加载完 Class 字节码文件并在办法区创立对应的 Class 对象之后,JVM 便会启动对该字节码流的校验,只有合乎 JVM 字节码标准的文件能力被 JVM 正确执行。具体如何验证是否符合规范,可自行 google。

筹备

为类的动态变量分配内存,并将其初始化为默认值。

筹备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些内存都将在办法区中调配。

  • 这时候进行内存调配的仅包含类变量(static),而不包含实例变量,实例变量会在对象实例化时随着对象一块调配在 Java 堆中。
  • 这里所设置的初始值通常状况下是数据类型默认的零值(如 0、0L、null、false 等),而不是被在 Java 代码中被显式地赋予的值。假如一个类变量的定义为:public static int value = 3;那么变量 value 在筹备阶段过后的初始值为 0,而不是 3。

解析

当通过筹备阶段之后,JVM 针对类或接口、字段、类办法、接口办法、办法类型、办法句柄和调用点限定符 7 类援用进行解析。这个阶段的次要工作是将其在常量池中的符号援用替换成间接其在内存中的间接援用。可自行 google。

初始化

为类的动态变量赋予正确的初始值,JVM 负责对类进行初始化,次要对类变量进行初始化。在 Java 中对类变量进行初始值设定有两种形式。

  • 申明类变量是指定初始值
  • 应用动态代码块为类变量指定初始值

更深刻的理解,请 google。

应用

当 JVM 实现初始化阶段之后,JVM 便开始从入口办法开始执行用户的程序代码。

卸载

当用户程序代码执行结束后,JVM 便开始销毁创立的 Class 对象,最初负责运行的 JVM 也退出内存。

类加载器品种

  • 启动类加载器,Bootstrap ClassLoader,加载 $JAVA_HOME/jre/lib/rt.jar,或者被 -Xbootclasspath 参数限定的类
  • 扩大类加载器,Extension ClassLoader,加载 $JAVA_HOME/jre/lib/ext 目录下的扩大 jar,或者被 java.ext.dirs 零碎变量指定的类
  • 应用程序类加载器,Application ClassLoader,加载 ClassPath 中的类库
  • 自定义类加载器,通过继承 ClassLoader 实现,个别是加载咱们的自定义类

双亲委派模型


双亲委派形容:

如果一个类收到了类加载的申请,不会本人先尝试加载,先找父类加载器去实现。当顶层启动类加载器示意无奈加载这个类的时候,子类才会尝试本人去加载。当回到最开始的发起者加载器还无奈加载时,并不会向下找,而是抛出 ClassNotFound 异样。(如果类 A 中援用了类 B,Java 虚拟机将应用加载类 A 的类加载器来加载类 B)

双亲委派的重要性:

java.lang.Object 类在 rt.jar,依照双亲委派的话它就只能被启动类加载器加载,因此 Object 在各类的类加载器环境中都是同一个类。如果不是双亲委派,那么用户在本人的 classpath 编写了一个 java.lang.Object 的类,那就无奈保障 Object 的唯一性。所以应用双亲委派,即便本人编写了,然而永远都不会被加载运行。可见双亲委派对于程序的稳定性很重要。

正文完
 0