1、jvm执行java程序的步骤
--加载:查找并加载类的二进制数据(class)
--连接:
-----验证:确保被加载的类的正确性
-----准备:为类的静态变量分配内存,并将其初始化为默认值
-----解析:把类中的符号引用转换为直接引用
--初始化:为类的静态变量赋予正确的初始化值。
1.1、 加载
1.1.1、jvm提供了三种类加载器
1)根类加载器(使用C++,程序员无法在java中获得该类)
2)扩展加载器,使用java
3)系统加载器sys(应用加载器AppClassLoader)
1.1.2、用户自己定义的类的加载器都是java.lang.Classloader的子类
解释:该类是一个抽象类abstract类。
1、如果是根类加载器加载那么Class.getclasslocader返回null,如果不是有根加载器则返回正确值。
package com.cn.jvm;
public class TestClassLoader {
public static void main(String[] args) throws ClassNotFoundException {
Class classzz = Class.forName("java.lang.String");
System.out.println(classzz.getClassLoader());
Class clazz = Class.forName("com.cn.jvm.C");
System.out.println(clazz.getClassLoader());
}
}
class C{
}
--------------结果----------------------
null
sun.misc.Launcher$AppClassLoader@6d4b473
-----------------结果---------------------------------
1.2初始化
1.2.1、解释一下,当一个类的静态变量为编译时可以获取时,该类不会被主动调用,如果一个类的静态变量为运行时赋值,则该类需要主动调用
package com.cn.jvm;
class FinaleTest1 {
public static final int x = 45;
static {
System.out.println("FinalTest1 block");
}
}
public class Test1 {
public static void main(String[] args) {
System.out.println(FinaleTest1.x);
}
}
--------------------结果------
45
package com.cn.jvm;
class FinaleTest2 {
public static String x = "2";
static {
System.out.println("FinalTest2 block");
}
}
public class Test2 {
public static void main(String[] args) {
System.out.println(FinaleTest2.x);
}
}
------------结果----------------
FinalTest2 block
2
1.2.2、接口的初始化
接口的初始化不会因为他的子接口或者实现类初始化二被初始化,只有当调用该接口的静态变量时才会被初始化。子接口被初始化父接口不会初始化。