美文网首页
深入JVM内核8 类连接和初始化

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

作者: 香沙小熊 | 来源:发表于2021-01-22 18:54 被阅读0次

1.类连接

1.1 类连接主要验证的内容
  • 类文件结构检查:按照JVM规范规定的类文件结构进行
  • 元数据验证:对字节码描述的信息进行语义分析,保证其符合Java语言规范要求
  • 字节码验证:通过对数据流和控制流进行分析,确保程序语义是合法和符合逻辑的。这里主要对方法进行校验
  • 符号引用验证:对类自身以外的信息,也就是常量池中的各种符号引用,进行匹配校验

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.类的卸载

  • 当代表一个类的Class对象不在引用,那么Class对象的生命周期就结束了,对应的在方法区中的数据也会被卸载
  • JVM自带的类加载器装载的类,是不是会卸载的,有用户自定义的类加载器加载的类是可以卸载的

相关文章

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

    1.类连接 1.1 类连接主要验证的内容 类文件结构检查:按照JVM规范规定的类文件结构进行 元数据验证:对字节码...

  • 深入JVM内核 目录

    深入JVM内核 目录 深入JVM内核1 初识JVM深入JVM内核2 JVM运行机制深入JVM内核3 常用JVM配置...

  • Java类加载机制与反射

    1. 类的加载、连接和初始化 1.1 JVM和类 当调用java程序时,会启动一个JVM进程 JVM中止的情形: ...

  • JVM问题(二)

    21. JVM初始化步骤? 1)假如这个类还没有被加载和连接,则程序先加载并连接该类。 2) 假如该类的直接父类还...

  • Java类加载与反射

    Java类加载与反射 类加载、连接、初始化 JVM和类 当运行某个Java程序时,将会启动一个Java虚拟机进程,...

  • 06 | JVM-类的加载

    类的加载步骤 JVM加载类的过程大致分为三步,装载(Load),连接(Link),初始化(Initialize) ...

  • ClassLoad

    类的加载过程:类的加载—>类的连接—>类的初始化 类加载器ClassLoader JVM 定义了两种类型的类加载器...

  • 类加载机制与反射(一)

    类的加载、连接和初始化 1.JVM和类 当调用java命令运行某个java程序时,该命令会启动一个java虚拟机进...

  • JVM之类加载机制

    当我们的程序要想使用某个类的时候,JVM则必须要加载并且初始化对这个类。加载过程大致分为加载、连接、初始化3个步骤...

  • 深入JVM内核1 初识JVM

    深入JVM内核 目录 1 JVM概念 JVM是Java Virtual Machine的简称。意味Java虚拟机虚...

网友评论

      本文标题:深入JVM内核8 类连接和初始化

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