Java虚拟机类加载机制

2020-01-19  本文已影响0人  MadnessXiong

1. 类加载的时机

类从被加载到虚拟机内存中开始,到卸载出内存为止它的整个生命周期包括:加载(loading),验证(Verification),准备(Preoaration),解析(Resolution),初始化(Initalization),使用(Using)和卸载(Unloading)7个阶段。其中验证,准备,解析3个部分统称为连接。

有且只有以上5种场景中的行为会触发类的初始化,这5种场景称为对一个类的主动引用。除此之外,所有引用类的方式都不会出发初始化,称为被动引用。接口和类的区别是,一个类在初始化时,要求其父类全部都已经初始化过了,但是一个接口在初始化时,并不要求其父接口全部都完成了初始化,只有在真正使用到父接口的时候,才会初始化

被动引用的例子:

//父类
public class SuperClass {
    
    static {
        System.out.println("初始化SuperCLass");
    }
    //父类静态方法
    public static void init(){}
    //常量
    public static final String INIT="init";
        
}
//子类
public class SubClass extends SuperClass{

    static {
        System.out.println("初始化SuperCLass");
    }
}
//通过子类调用父类静态方法
 SubClass.init();
//数组
SuperClass[] superClasses = new SuperClass[1];
//引用常量
System.out.println(SuperClass.INIT);

以上代码中调用SubClass.init()后不会触发子类的初始化

2. 类加载的过程(这里只关注准备及初始化阶段)

public class SubClass extends SuperClass{
    
    static {
        //可以给变量赋值
      I=1;
      //这句编译器会提示非法向前引用  
      System.out.println(""+i);
    }

    static int I=0;
}

4. 类加载器

应用程序都是由这3种类加载器互相配合进行加载的,如果有必要还可以加入自己定义的类加载器,它们的关系如下:


image-20200119204213241.png

类加载器之间的这种层次关系,称为加载器的双亲委派模型。双亲委派模型要求除了顶层的启动类加载器外,其他的类加载器都应当有自己的父类加载器,这里的类加载器之间的父子关系一般使用组合关系来复用父加载器的代码。

双亲委派模型的工作过程是:如果一个类加载器收到了类加载请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。

双亲委派模型保证了一个类无论哪一个类加载器加载,最终都会委派给最顶层的加载器去加载(除非找不到),这样就保证了这个类在各种类加载器环境中都是同一个类。

上一篇 下一篇

猜你喜欢

热点阅读