Java代码中,类型的加载、连接与初始化过程都是在程序运行期间完成的 类型:可以理解为一个class 加载:查找并加载类的二进制数据,最常见的情况是将已经编译完成的类的class文件从磁盘加载到内存中 连接:确定类型与类型之间的关系,对于字节码的相关处理 验证:确保被加载的类的正确性 准备:为类的静态变量分配内存,并将其初始化为默认值。但是在到达初始化之前,类变量都没有初始化为真正的初始值 解析:在类型的常量池中寻找类、接口、字段和方法的符号引用,把这些符号引用转换为直接引用的过程 初始化:为类的静态变量赋予正确的初始值 使用:比如创建对象,调用类的方法等 卸载:类从内存中销毁 理解:public static int number = 666; 上面这段代码,在类加载的连接阶段,为对象number分配内存,并初始化为0;然后再初始化阶段在赋予正确的初始值:666 Java程序对类的使用方式可分为两种 主动使用 创建类的实例 访问某个类或接口的静态变量,或者对静态变量赋值 调用类的静态方法 反射 初始化类的子类 Java虚拟机启动时被标明为启动类的类(包含main方法) JDK1.7开始提供的动态语言支持(java.lang.invoke.MethodHandle实例的解析结果REF_getStatic,REF_putStatic,REF_invokeStatic句柄对应的类没有初始化,则初始化) 被动使用 除了主动使用的七种情况之外,其他使用Java类的方法都被看作是对类的被动使用,都不会导致类的初始化 所有的Java虚拟机实现必须在每个类或接口被Java程序“首次主动使用”时才初始化他们 代码一 public class Test01 { public static void main(String[] args) { System.out.println(Child01.str); } } class Father01 { public static String str = "做一个好人!"; static { System.out.println("Father01 static block"); } } class Child01 extends Father01 { static { System.out.println("Child01 static block"); } } 运行结果做一个好人! Father01 static block 做一个好人! 代码二 public class Test01 { public static void main(String[] args) { System.out.println(Child01.str2); } } class Father01 { public static String str = "做一个好人!"; static { System.out.println("Father01 static block"); } } class Child01 extends Father01 { public static String str2 = "做一个好人!"; static { System.out.println("Child01 static block"); } } 运行结果 Father01 static block Child01 static block 做一个好人! 分析: 代码一中,我们通过子类调用父类中的str,这个str是在父类被定义的,对Father01主动使用,没有主动使用Child01,故Child01的静态代码块没有执行,父类的静态代码块被执行了。 -> 对于静态字段来说,只有直接定义了该字段的类才会被初始化。 代码二中,对Child01主动使用;根据主动使用的7种情况,调动类的子类时,其所有的父类都会被先初始化,所以Father01会被初始化。 -> 当一个类初始化时,要求其父类全部都已经初始化完毕了。 以上验证的是类的初始化情况,那么如何验证类的加载情况呢,可以通过在启动的时候配置虚拟机参数:-XX:+TraceClassLoading查看 运行代码一,查看输出结果,可以看见控制台打印了very多的日志,第一个加载的是java.lang.Object类(不管加载哪个类,他的父类一定是Object类),后面是加载的一系列jdk的类,他们都位于rt包下。往下查看,可以看见Loaded classloader.Child01,说明即使没有初始化Child01,但是程序依然加载了Child01类。 [Opened /usr/local/jdk1.8/jre/lib/rt.jar] [Loaded java.lang.Object from /usr/local/jdk1.8/jre/lib/rt.jar] ... [Loaded java.lang.Void from /usr/local/jdk1.8/jre/lib/rt.jar] [Loaded classloader.Father01 from file:/home/fanxuan/Study/java/jvmStudy/out/production/jvmStudy/] [Loaded classloader.Child01 from file:/home/fanxuan/Study/java/jvmStudy/out/production/jvmStudy/] Father01 static block 做一个好人! [Loaded java.lang.Shutdown from /usr/local/jdk1.8/jre/lib/rt.jar] [Loaded java.lang.Shutdown$Lock from /usr/local/jdk1.8/jre/lib/rt.jar] 拓展:JVM参数介绍 因为前一章节使用了JVM参数,所以对其做一下简单的介绍 所有的JVM参数都是以-XX:开头的 如果形式是:-XX:+