JVM加载类过程的总结

来源:互联网 发布:sarah brightman 知乎 编辑:程序博客网 时间:2024/06/07 03:56
JVM类的加载
JVM是Java虚拟机,每当一个Java程序运行时都会有一个JVM实例,只有当程序结束运行后这个JVM才退出。Jvm实例通过调用MAIN函数来启动一个JAVA 程序,也就是找到main函数然后进行相关类的加载。
类的加载主要有三个步骤:
1.装载。根据查找路径找到相应的class文件,然后导入。
2.链接。具体再分为三个步骤
     (1)检查 检查class文件的正确性
     (2)准备 给类中的静态变量分配空间
     (3)解析 将符号引用转换为直接引用(可选)
3.初始化。对静态变量和静态代码块块执行初始化工作

具体的举个例子来说明一下(代码来自互联网)
classInsect
{
     privateinti=9;
     protectedintj;
     Insect()
     {
           System.out.println("i="+i+" j="+j);
           j= 39;
     }
     privatestaticintx= printInit("static Insect.x initialized");
     staticintprintInit(Strings)
     {
           System.out.println(s);
           return47;
     }
     
}
publicclassBeetleextendsInsect
{
     privateintk= printInit("Bettle.k initialized");
     publicBeetle()
     {
           System.out.println("k="+k+" j="+j);
     }
     privatestaticintx2= printInit("static beetle initialized");
     publicstaticvoidmain(String[]args)
     {
           System.out.println("bettle constructor");
           Beetleb= new Beetle();
     }
}
运行结果:
对于这个java文件,在运行时程序一开始试图找到Beetle的main方法然后加载Beetle的class文件,在class文件加载的过程中,发现这个Beetle类继承了另外一个类Insect所以程序需要先加载Insect的class文件。在加载过程中会执行类加载的三个步骤,遇到静态变量惊醒初始化,之后再加载自身的class文件,同样遇到static修饰的也会初始化。所以会先输出
static Insect.x initialized
static beetle initialized
此时如果Insect类继承了另外一个类时,以同样的方法类推。

总结类初始化的顺序:
父类静态变量,父类静态代码块,子类静态变量,子类静态代码块,父类非静态变量,父类非静态代码块,父类构造函数,子类非静态变量,子类非静态代码块,子类构造函数。

ps: 如果去掉main函数,则会出现如下结果:
JVM类的加载
JVM是Java虚拟机,每当一个Java程序运行时都会有一个JVM实例,只有当程序结束运行后这个JVM才退出。Jvm实例通过调用MAIN函数来启动一个JAVA 程序,也就是找到main函数然后进行相关类的加载。
类的加载主要有三个步骤:
1.装载。根据查找路径找到相应的class文件,然后导入。
2.链接。具体再分为三个步骤
     (1)检查 检查class文件的正确性
     (2)准备 给类中的静态变量分配空间
     (3)解析 将符号引用转换为直接引用(可选)
3.初始化。对静态变量和静态代码块块执行初始化工作

具体的举个例子来说明一下(代码来自互联网)
classInsect
{
     privateinti=9;
     protectedintj;
     Insect()
     {
           System.out.println("i="+i+" j="+j);
           j= 39;
     }
     privatestaticintx= printInit("static Insect.x initialized");
     staticintprintInit(Strings)
     {
           System.out.println(s);
           return47;
     }
     
}
publicclassBeetleextendsInsect
{
     privateintk= printInit("Bettle.k initialized");
     publicBeetle()
     {
           System.out.println("k="+k+" j="+j);
     }
     privatestaticintx2= printInit("static beetle initialized");
     publicstaticvoidmain(String[]args)
     {
           System.out.println("bettle constructor");
           Beetleb= new Beetle();
     }
}
运行结果:
对于这个java文件,在运行时程序一开始试图找到Beetle的main方法然后加载Beetle的class文件,在class文件加载的过程中,发现这个Beetle类继承了另外一个类Insect所以程序需要先加载Insect的class文件。在加载过程中会执行类加载的三个步骤,遇到静态变量惊醒初始化,之后再加载自身的class文件,同样遇到static修饰的也会初始化。所以会先输出
static Insect.x initialized
static beetle initialized
此时如果Insect类继承了另外一个类时,以同样的方法类推。

总结类初始化的顺序:
父类静态变量,父类静态代码块,子类静态变量,子类静态代码块,父类非静态变量,父类非静态代码块,父类构造函数,子类非静态变量,子类非静态代码块,子类构造函数。

ps: 如果去掉main函数,则会出现如下结果:

0 0
原创粉丝点击