深入JVM内核8 类连接和初始化

2021-01-22  本文已影响0人  香沙小熊

1.类连接

1.1 类连接主要验证的内容

1.2 类连接中的解析

所谓解析就是把常量池中的符号引用转换成直接引用的过程,包括:符号引用:以一组无歧义的符号来描述所引用的目标,与虚拟机的实现无关

2.类的初始化

类的初始化就是为类的静态变量赋初始值,或者说是执行类构造器<clinit>方法的过程

  1. 如果类还没有加载和连接,就先加载和连接
  2. 如果类存在父类,且父类没有初始化,就先初始化父类
public class MyParent {
    static {
        System.out.println("my parent class init");
    }
}
public class MyChild extends MyParent {
    static {
        System.out.println("my child class init");
    }
}
public class Test {

    public static void main(String[] args) {
        MyChild myChild = new MyChild();

    }
}
my parent class init
my child class init
  1. 如果类中存在初始化语句,就依次执行这些初始化语句
public class MyChild extends MyParent {


    static {
        System.out.println("my child class init");
    }

    static {
        System.out.println("my child class block 1");
    }
    private static final int a = 5;
    static {
        System.out.println("my child class block 2 a="+a);
    }
}
my parent class init
my child class init
my child class block 1
my child class block 2 a=5
  1. 如果是接口的话:
    • 初始化一个类的时候,并不会先初始化它实现的接口
    • 初始化一个接口时,并不会初始化它的父接口
    • 只有当程序首次使用接口里面的变量或者是调用接口方法的时候,才会导致接口初始化
public interface Api {
    public static String str = "now in api";

    public void t1();
}
public class MyChild extends MyParent implements Api{


    static {
        System.out.println("my child class init");
    }

    static {
        System.out.println("my child class block 1");
    }
    private static final int a = 5;
    static {
        System.out.println("my child class block 2 a="+a);
    }

    @Override
    public void t1() {

        System.out.println("now in mychild t1");
    }
}
public class Test1 {

    public static void main(String[] args) {
        MyChild myChild = new MyChild();

        System.out.println("mychild.str=="+myChild.str);
    }
}
my parent class init
my child class init
my child class block 1
my child class block 2 a=5
mychild.str==now in api

ZHI
5.调用Classloader类的loadClass方法来转载一个类,并不会初始化这个类,不是对类的主动调用

    public static void main(String[] args) throws ClassNotFoundException {
        MyClassLoader  myClassLoader = new MyClassLoader("myClassloader1");
        Class cls1 = myClassLoader.loadClass("com.kpioneer.demo.jvm.classinit.MyChild");
        System.out.println("over=======");
    }
over=======
Classloader调用MyChild,里面的静态代码块,并没有被调用。
2.1.类的初始化时机

Java程序对类的使用方式分成:主动使用和被动使用,JVM必须在每个类或接口"首次主动使用"时才初始化它们;被动使用类不会导致类的初始化,主动使用的情况:
1)创建类实例
2)访问某个类或接口的静态变量
3)调用类的静态方法

public class MyChild extends MyParent implements Api {


    private static final int a = 5;

    static {
        System.out.println("my child class init");
    }

    static {
        System.out.println("my child class block 1");
    }

    static {
        System.out.println("my child class block 2 a=" + a);
    }

    public static void t2() {
        System.out.println("now in mychild t2");
    }

    @Override
    public void t1() {

        System.out.println("now in mychild t1");
    }
}
    public static void main(String[] args) throws ClassNotFoundException {

        MyChild.t2();

    }
my parent class init
my child class init
my child class block 1
my child class block 2 a=5
now in mychild t2

4)反射某个类

    public static void main(String[] args) throws ClassNotFoundException {

        Class cls = Class.forName("com.kpioneer.demo.jvm.classinit.MyChild");
    }
my parent class init
my child class init
my child class block 1
my child class block 2 a=5

5)初始化某个类的子类,而父类还没有初始化
6)JVM启动的时候运行的主类

public class Test {

    static {
        System.out.println("now Test class init");
    }

    public static void main(String[] args) throws ClassNotFoundException {


        Class cls = Class.forName("com.kpioneer.demo.jvm.classinit.MyChild");
    }
}
now Test class init
my parent class init
my child class init
my child class block 1
my child class block 2 a=5

7)定义了default方法的接口,当接口实现类初始化时

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Api api = (Api)(Class.forName("com.kpioneer.demo.jvm.classinit.MyChild").newInstance());
        api.t3();
    }
my parent class init
my child class init
my child class block 1
my child class block 2 a=5
now in api t3()

3.类的卸载

上一篇 下一篇

猜你喜欢

热点阅读