美文网首页
你了解类的加载机制吗?

你了解类的加载机制吗?

作者: yunqing_71 | 来源:发表于2019-11-03 09:41 被阅读0次

定义:当程序主动使用某个类时,如果该类还没被加载到内存中,那么系统会通过加载、连接、初始化这三个步骤对该类进行初始化,JVM通常将会连续完成这三个步骤,所以一般情况下这三个步骤统称为类的加载。

实际上类的加载就是将类的class文件读进内存,并为之创建一个java.lang.Class对象。

类的初始化

当类被加载之后,系统会生成一个对应的Class文件,接着进入连接阶段,连接阶段负责把类的二进制数据合并到JRE中。之后进入类的初始化阶段,初始化阶段JVM负责对类进行初始化,主要是对类变量进行初始化,两种方式对类变量进行初始化①声明类变量时指定初始化值②是用静态代码块指定初始化值。

类的初始化包含以下几个步骤:

①如果类还没被加载和连接,先进行加载、连接

②如果类的直接父类还没被初始化则先初始化直接父类,类推到Object类,所以Object类永远是最先被初始化的类

③系统会依次执行初始化语句。(即前边的初始化值有可能在后面被覆盖)

/**
 * 男人类继承自人类
 */
class Man extends Person{
    static{
        b = 100;
    }
    private static int b = 2;

    private static int c = 3;

    private static int d = 4;

    private static int e;

    static {
        d = 200;
    }

    public static void main(String[] args) {
        System.out.println("a = " + Person.a);
        System.out.println("b = " + Man.b);
        System.out.println("c = " + Man.c);
        System.out.println("d = " + Man.d);
        System.out.println("e = " + Man.e);

    }
}

/**
 * 人类
 */
class Person {

    static int a = 1;

}
#输出
a = 1
b = 2
c = 3
d = 200
e = 0

类初始化的时机

当Java程序首次通过下面6个方式使用某个类或接口的时候,会初始化此类或接口。

①创建类的实例。包括new一个实例,反射创建实例,反序列化创建实例。

②调用某个类的静态方法(类方法)

③访问类或者接口的类变量,或者为类变量赋值

④使用反射强制创建某个类或接口的Class对象,例如Class.for("Person")若系统还没初始化Person类,这行代码会初始化Person类,并返回Person类对应的Class对象。

⑤初始化某个类的子类,该子类的所有父类都会被初始化。

⑥直接使用java.exe运行某个主类。

注意:当类变量被final修饰的时候,如果类变量的值在编译时候能确定,在使用该类变量的时候不会初始化该类,因为相当于使用了一个常量。如下:


import java.time.LocalDateTime;

public class finalTest {

    public static void main(String[] args) {
        System.out.println(Dog.b);
        System.out.println(Cat.a);
    }
}

class Cat{

    static{
        System.out.println("初始化Cat类");
    }

    /**
     * 编译时候确定了a的值
     */
    final static String a = "1000";

}

class Dog{
    static{
        System.out.println("初始化Dog类");
    }

    /**
     * 编译时并没有确定b的值
     */
    final static String b = LocalDateTime.now().toString();
}
#输出
初始化Dog类
2019-11-02T11:22:18.823
1000

另一注意点:当使用ClassLoader类的loadClass()来加载某个类时候,并不会初始化该类,使用Class的forName()静态初始化方法才会强制初始化该类。

类加载器

类的加载由类加载器完成,类加载器通常由JVM提供,JVM提供的类加载器是系统类加载器,其次,开发者可以通过集成ClassLoader类来创建自己的类加载器。

当JVM启动时,会形成由三个类加载器组成的初始类加载器层次结构:

①Bootstrap ClassLoader: 根类加载器

②Extension ClassLoader: 扩展类加载器

③System ClassLoader: 系统类加载器

JVM的类加载机制主要有以下三种:

①全盘负责:当一个类加载器负责加载某个Class时,该Class所依赖和引用的其他Class也将由该类加载器负责载入。

②父类委托:先由父类加载器试图加载该Class,只有当父类加载器无法加载该类时,才会从自己的类路径中加载该类。

③缓存机制:保证所有的加载过的Class都会被缓存,当程序需要使用某个Class时,类加载器先从缓存区中查找,只有在缓存区不存在该Class对象时,系统才会读取该类对应的二进制文件,转换成Class对象,存入缓存区。

类加载器加载Class大致要经过以下几个步骤:

①在缓存区检查该Class是否载入过,如果有则直接第⑧步,否则执行第②步。

②如果父类加载器不存在(如果父类加载器不存在,则parent一定是根加载器,或者本身就是根加载器,因为根加载器不是java实现的,所以返回null)直接跳第④步,如果父类加载器存在,则执行第③步。

③请求使用父类加载器去载入目标类,如果成功载入则跳第⑧步,否则执行第⑤步

④请求使用根类加载器载入目标类,如果成功载入则跳第⑧步,否则跳第⑦步

⑤当前类加载器尝试寻找Class文件(从与此加载器相关的类路径中寻找)如果找到执行第⑥步,找不到执行第⑦步

⑥从文件中载入Class,成功载入跳第⑧步

⑦抛出ClassNotFoundException异常

⑧返回对应的java.lang.Class对象

相关文章

  • 你了解类的加载机制吗?

    定义:当程序主动使用某个类时,如果该类还没被加载到内存中,那么系统会通过加载、连接、初始化这三个步骤对该类进行初始...

  • 双亲委派机制

    说到双亲委派机制,首先你要了解,什么是类加载器,下面就先简单说一下类加载器,后面在对双亲委派机制进行了解。 一、类...

  • JVM学习(二)类加载器

    目录 一、类加载器 还记得类加载机制吗?类加载机制的各阶段是加载、连接(验证、准备、解析)、初始化、使用、卸载。可...

  • Java类加载机制

    你知道Java的类加载机制吗?字节码文件时如何被加载使用的你?今天我们从以下几个方面,一起聊聊类加载。 类加载过程...

  • 类加载机制(一)

    加载机制系列类加载机制(一)类加载机制(二)类加载机制(三) 类加载机制 1.JVM把class文件加载到内存,对...

  • 类加载机制(三)

    加载机制系列类加载机制(一)类加载机制(二)类加载机制(三)类加载器 这里引用尚学堂的的几张图片 demo: 结果:

  • 了解类加载机制

    知道下面的程序输出的内容么?

  • 安卓类加载机制

    热修复、插件化很多技术都是基于安卓类加载机制实现,所以对安卓类加载机制了解很有必要

  • JVM——类加载机制

    前言 今天就来介绍类的加载机制以及双亲委派机制。 JVM 类加载机制 JVM 类加载的五个阶段 JVM 类加载机制...

  • 类加载机制(二)

    加载机制系列类加载机制(一)类加载机制(二)类加载机制(三)类的加载全过程中的主动引用与被动引用 类的主动引用(会...

网友评论

      本文标题:你了解类的加载机制吗?

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