JVM类加载顺序
今天,梳理一下类加载顺序,从测试结果来推测类加载顺序。
第一步:基础准备
父类:
public********classParent {
publicString parentProperty=“ParentPropertyValue”;
public********staticString staticParentProperty=“StaticParentPropertyValue”;
static{
System._out_.println(“父类的静态代码块”);
}
{
System._out_.println(“父类的代码块”);
}
publicParent(){
System._out_.println(“父类类的构造方法”);
};
}
子类:
public********classSub extendsParent{
public********staticString staticSubproperty=“StaticSubPropertyValue”;
publicString subproperty=“SubPropertyValue”;
static{
System._out_.println(“子类的静态代码块”);
}
{
System._out_.println(“子类的代码块”);
}
publicSub(){
System._out_.println(“子类的构造方法”);
};
}
@Test
public********voidtest1(){
System._out_.println(“jvm”);
}
Console:jvm
得出结论:1、jvm并不是一次性把所有的class文件都加载进去,只有在用到类时才会加载class文件.
@Test
public********voidtest2(){
System._out_.println(Parent.staticParentProperty);
}
Console:父类的静态代码块
StaticParentPropertyValue
得出结论:2、jvm在加载过程中先加载静态代码块、静态属性.
@Test
public********voidtest3(){
Parent p=newParent();
}
Console:父类的静态代码块
父类的代码块
父类类的构造方法
得出结论:3、jvm在加载过程中先加载静态代码块->实例初始化代码块->实例初始化构造函数.
@Test
public********voidtest4(){
System._out_.println(Sub.staticParentProperty);
}
Console:父类的静态代码块
StaticParentPropertyValue
注意:这里是子类应用父类的静态属性。。。。(原本是想写test5的,写错了哈哈)
得出结论:4、虽然这里用的是Sub名称,但是jvm完全没有加载Sub类,这是预料之外的结果。大胆猜测:jvmx加载时并不是根据全限量名来加载指定的类,子类的全量名估计是可以代替所有的父类,这大概就是****里氏替换原则:任何基类可以出现的地方,子类一定可以出现。****jvm是根据后面的属性来确定具体加载哪个类。
@Test
public********voidtest5(){
System._out_.println(Sub.staticSubproperty);
}
Console:父类的静态代码块
子类的静态代码块
StaticSubPropertyValue
得出结论:5、jvm在加载子类过程中,先加载父类,再加载子类,注意这里和实例初始化没关系哦,这也在侧面说明jvm的加载顺序是:加载class文件->变成对应的java类->初始化实例。
@Test
public********voidtest6(){
Parent p=newParent();
ParentB pb=newParentB();
}
Console:父类的静态代码块
父类的代码块
父类类的构造方法
父类的静态代码块b
父类的代码块b
父类类的构造方法b
得出结论:6、在test5的基础上验证了,jvm是遇到哪个类就先加载哪个类。
@Test
public********voidtest7(){
System._out_.println(Sub.staticSubproperty);
System._out_.println(SubB.staticSubpropertyb);
}
Console:父类的静态代码块
子类的静态代码块
StaticSubPropertyValue
子类的静态代码块b
StaticSubPropertyValueb
得出结论:7、在test5的基础上验证了,jvm在加载一个类时会检查这个class是否已加载,若加载就不再加载,若没加载就立即加载。
@Test
public********voidtest8(){
Sub s=newSub();
}
Console:父类的静态代码块
子类的静态代码块
父类的代码块
父类类的构造方法
子类的代码块
子类的构造方法
得出结论:8、jvm创建子类实例时:加载父类->加载子类->初始化父类实例->初始化子类实例。
先总结一下:
1、jvm并不是一次性把所有的class文件都加载进去,只有在用到类时才会加载class文件.
2、jvm在加载过程中先加载静态代码块、静态属性.
3、jvm在加载过程中先加载静态代码块->实例初始化代码块->实例初始化构造函数.
4、虽然这里用的是Sub名称,但是jvm完全没有加载Sub类,这是预料之外的结果。大胆猜测:jvmx加载时并不是根据全限量名来加载指定的类,子类的全量名估计是可以代替所有的父类,这大概就是****里氏替换原则:任何基类可以出现的地方,子类一定可以出现。****jvm是根据后面的属性来确定具体加载哪个类。
5、jvm在加载子类过程中,先加载父类,再加载子类,注意这里和实例初始化没关系哦,这也在侧面说明jvm的加载顺序是:加载class文件->变成对应的java类->初始化实例。
6、jvm是遇到哪个类就先加载哪个类。
7、jvm在加载一个类时会检查这个class是否已加载,若加载就不再加载,若没加载就立即加载。
8、jvm创建子类实例时:加载父类->加载子类->初始化父类实例->初始化子类实例。