java虚拟机和程序的生命周期 JVM
1.1程序的生命周期
开始:通过java命令运行一个java程序(.class文件)
运行:java虚拟机从开始到终止(正常结束/出现异常或者错误而异常终止/System.exit()/操作系统错误而导致java虚拟机终止)分为:加载,连接,初始化
结束
1.2
1.2.1 加载 加载各种.class文件, 在堆区中创建java.lang.Class对象,封装方法区的数据结构
1.2.2 连接 分为验证,准备,解析
验证:验证Class对象封装的数据结构的正确性,错误抛出相应的Error对象。
准备:为类的静态变量分配内存,设置默认值
解析:将符号引用替换为直接引用
1.2.3 初始化
执行初始化语句,为类的静态变量赋予初始值。(静态变量有默认值)
初始化语句:声明语句,静态代码块,按照文件中的先后顺序执行。
1.如果这个类没有加载和连接,那就先进行加载和连接
2 类有直接父类,且没有被初始化,则先初始化父类,
3 如果类中存在初始化语句,那么久一次执行这些初始化语句
1.2.4 类的初始化时机:(主动使用)
1.创建类的实例
2.调用类的静态方法
3访问某个类或接口的静态方法,或者对该静态方法赋值。
4.调用Java API中某些反射方法
5.初始化一个类的子类
6.Java虚拟机被标明为启动类
3个时机(不视为主动使用,不会初始化)
1.final类型的静态变量,如果编译时就能计算出变量的取值,那么这种变量看做编译时常量。
2.final类型静态变量,编译时不能计算出,看做主动使用,即初始化
3.只有当前程序访问的静态变量或静态方法的确在当前类或者接口中定义时,才看到主动使用,否则不初始化。
class Base{
static int a=1;
static { System.out.println("Init Base"); }
}
class Sub extends Base{
static int b=1;
static { System.out.println("init Sub"); }
}
public class InitTester { //无父类,直接初始化本类
static { System.out.println("init initTester"); }
public static void main(String[] args) {
System.out.println("b="+Sub.b); } //访问Sub.b时,依次加载Base类,Sub类
}
运行结果:
init initTester
Init Base
init Sub
b=1
修改:
public class InitTester { //无父类,从本类初始化
static {
System.out.println("init initTester"); //1
}
public static void main(String[] args) {
Base base;
System.out.println("After defining base");//2
base=new Base(); // 3 初始化 base
System.out.println("After creating an Object of Base");//4
System.out.println("a="+base.a); //base已经初始化 a=1
System.out.println("b="+Sub.b); //5. 初始化sub 6.sub.b=1
}
}
运行:
init initTester
After defining base
Init Base
After creating an Object of Base
a=1
init Sub
b=1
class Base{
static int a=1;
static { System.out.println("Init Base");
}
static void method(){
System.out.println("method of Base"); }
}
class Sub extends Base{
static { System.out.println("init Sub"); }
}
public class InitTester{
public static void main(String[] args) {
System.out.println("a="+Sub.a);
Sub.method(); }
}
运行结果:
Init Base
a=1
method of Base