Java类加载机制

java类加载机制

类的生命周期

类的生命周期包括7个阶段:加载 、验证、准备、解析、初始化、使用和卸载

类的初始化场景

  1. 遇到指定的字节码指令的时候,4种指定的字节码 ,new、putstatic、getstatic和invokestatic
  2. 子类初始化过程中,如果父类没有初始化的情况下,会触发父类的初始化
  3. 使用了反射包中的方法对类进行反射调用的时候,会触发初始化
  4. 当JVM启动的时候,用户指定一个要执行的主类的时候,虚拟机会触发初始化那个主类
  5. JDK1.7中动态语言支持时,如果方法句柄存在static关键字的时候,也会初始化

类不初始化的场景

场景一 :

通过子类引用父类的静态变量时,不会导致子类的初始化过程

代码如下:


public class SSClass
{
    static
    {
        System.out.println("SSClass");
    }
}    
public class SuperClass extends SSClass
{
    static
    {
        System.out.println("SuperClass init!");
    }
 
    public static int value = 123;
 
    public SuperClass()
    {
        System.out.println("init SuperClass");
    }
}
public class SubClass extends SuperClass
{
    static
    {
        System.out.println("SubClass init");
    }
 
    static int a;
 
    public SubClass()
    {
        System.out.println("init SubClass");
    }
}
public class NotInitialization
{
    public static void main(String[] args)
    {
        System.out.println(SubClass.value);
    }
}

输出的结果:
SSClass
SuperClass init!
123

场景二:

通过数组来引用类,不会触发该类初始化 例如:SubClass[] array = new SubClass[10] 原因在于,这时候的字节码指令是newarray

场景三:

当类变量被final关键字修饰的时候,引用ConstanValue不会触发该类初始化
原因:这种常量在类的准备阶段已经存放在常量池里了,调用和该类没有太大关系

应用测试题

package com.zzjmay;

public class TestJVM {


        public static void main(String[] args)
        {
            staticFunction();
        }

        static TestJVM st = new TestJVM();

        static
        {
            System.out.println("1");
        }

        {
            System.out.println("2");
        }

        TestJVM()
        {
            System.out.println("3");
            System.out.println("a="+a+",b="+b);
        }

        public static void staticFunction(){
            System.out.println("4");
        }

        int a=110;
        static int b =112;

}

输出的结果是
2
3
a=110 ,b=0
1
4

注意:
对象初始化的步骤是先初始化成员变量,再初始化构造器
类初始化 按照代码顺序执行,如果存在嵌套对象初始化,先执行对象初始化

你可能感兴趣的:(Java类加载机制)