jvm类加载顺序

本文详细探讨了JVM的类加载顺序,通过测试案例揭示了以下规律:1) 类在使用时才加载;2) 首先加载静态代码块和静态属性;3) 加载顺序为静态代码块 -> 实例初始化代码块 -> 构造函数;4) 子类加载时先加载父类;5) 创建子类实例时,会先加载父类并初始化。这些深入了解有助于优化Java应用程序的性能和内存使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JVM类加载顺序

今天,梳理一下类加载顺序,从测试结果来推测类加载顺序。

第一步:基础准备

父类:

public class Parent {

public  String parentProperty="ParentPropertyValue";

public static String staticParentProperty="StaticParentPropertyValue";

static{

System.out.println("父类的静态代码块");

}

{

System.out.println("父类的代码块");

}

public Parent(){

System.out.println("父类类的构造方法");

};

}

子类:

public class Sub extends Parent{

 

public static String staticSubproperty="StaticSubPropertyValue";

public  String subproperty="SubPropertyValue";

static{

System.out.println("子类的静态代码块");

}

{

System.out.println("子类的代码块");

}

public Sub(){

System.out.println("子类的构造方法");

};

}

@Test

public void test1(){

System.out.println("jvm");

}

Console:jvm

得出结论1jvm并不是一次性把所有的class文件都加载进去,只有在用到类时才会加载class文件.

 

@Test

public void test2(){

System.out.println(Parent.staticParentProperty);

}

Console:父类的静态代码块

StaticParentPropertyValue

 

得出结论2jvm在加载过程中先加载静态代码块、静态属性.

 

@Test

public void test3(){

Parent p=new Parent();

}

 

Console:父类的静态代码块

父类的代码块

父类类的构造方法

 

得出结论3jvm在加载过程中先加载静态代码块->实例初始化代码块->实例初始化构造函数.

 

@Test

public void test4(){

System.out.println(Sub.staticParentProperty);

}

Console:父类的静态代码块

StaticParentPropertyValue

 

注意:这里是子类应用父类的静态属性。。。。(原本是想写test5的,写错了哈哈)

得出结论4、虽然这里用的是Sub名称,但是jvm完全没有加载Sub类,这是预料之外的结果。大胆猜测:jvmx加载时并不是根据全限量名来加载指定的类,子类的全量名估计是可以代替所有的父类,这大概就是里氏替换原则:任何基类可以出现的地方,子类一定可以出现jvm是根据后面的属性来确定具体加载哪个类。

@Test

public void test5(){

System.out.println(Sub.staticSubproperty);

}

 

Console:父类的静态代码块

子类的静态代码块

StaticSubPropertyValue

 

得出结论5jvm在加载子类过程中,先加载父类,再加载子类,注意这里和实例初始化没关系哦,这也在侧面说明jvm的加载顺序是:加载class文件->变成对应的java->初始化实例

@Test

public void test6(){

Parent p=new Parent();

ParentB pb=new ParentB();

}

Console:父类的静态代码块

父类的代码块

父类类的构造方法

父类的静态代码块b

父类的代码块b

父类类的构造方法b

 

得出结论6、在test5的基础上验证了,jvm是遇到哪个类就先加载哪个类

@Test

public void test7(){

System.out.println(Sub.staticSubproperty);

System.out.println(SubB.staticSubpropertyb);

}

Console:父类的静态代码块

子类的静态代码块

StaticSubPropertyValue

子类的静态代码块b

StaticSubPropertyValueb

 

得出结论7、在test5的基础上验证了,jvm在加载一个类时会检查这个class是否已加载,若加载就不再加载,若没加载就立即加载

 

@Test

public void test8(){

Sub s=new Sub();

}

Console:父类的静态代码块

子类的静态代码块

父类的代码块

父类类的构造方法

子类的代码块

子类的构造方法

 

得出结论8jvm创建子类实例时:加载父类->加载子类->初始化父类实例->初始化子类实例

 

先总结一下:

1、jvm并不是一次性把所有的class文件都加载进去,只有在用到类时才会加载class文件.

2jvm在加载过程中先加载静态代码块、静态属性.

3jvm在加载过程中先加载静态代码块->实例初始化代码块->实例初始化构造函数.

4、虽然这里用的是Sub名称,但是jvm完全没有加载Sub类,这是预料之外的结果。大胆猜测:jvmx加载时并不是根据全限量名来加载指定的类,子类的全量名估计是可以代替所有的父类,这大概就是里氏替换原则:任何基类可以出现的地方,子类一定可以出现jvm是根据后面的属性来确定具体加载哪个类。

5jvm在加载子类过程中,先加载父类,再加载子类,注意这里和实例初始化没关系哦,这也在侧面说明jvm的加载顺序是:加载class文件->变成对应的java->初始化实例

6jvm是遇到哪个类就先加载哪个类

7jvm在加载一个类时会检查这个class是否已加载,若加载就不再加载,若没加载就立即加载

8jvm创建子类实例时:加载父类->加载子类->初始化父类实例->初始化子类实例

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值