标签:st3 语言 src puts 提升 内存 出现 war string
一直想好好的了解一下JVM,这次就来一起了解一下JVM是如何实现类的加载过程的。
类加载的生命周期
1. 加载
5种类加载情况:
因为Java类加载是不关心这个文件来自哪里?
所有Java的对象可以来自Jar,war,网络,CGlib,数据库等等。
使用到对象才会加载。
2. 验证
3. 准备
为静态变量分配内存、为基础数据类型赋初值,
如果被final修饰,在编译的时候会给属性添加ConstantValue属性,准备阶段直接完成赋值操作,无需赋初值。
4. 解析
间接引用转直接引用。
间接引用:指向常量池。
直接引用:指向内存地址。
5. 初始化
执行静态代码段(静态代码块,静态变量):clinit
测试代码写了一个静态变量b 通过字节码文件也能清楚的看到信息。
静态代码的执行顺序和定义的顺序一致,改点可以通过案例说明。
public class JvmTest1 { public static void main(String[] args) { Test1 test1 = Test1.getTest(); System.out.println(Test1.val1); System.out.println(Test1.val2); } } class Test1{ public static int val1 ; Test1(){ val1++; val2++; } public static Test1 instance = new Test1(); public static int val2 = 1 ; // 该代码放在在初始化代码 public static Test1 getTest(){ return instance; } }
运行结果:
运行结果是1和1 ,造成这个结果的原因就是静态代码的顺序执行,先创建了对象,对象中构造函数执行了, 后面再执行 public static int val2 = 1 ,值就被覆盖回去了。
6. 使用
对象已经初始化完成,这个对象就可以再其他地方被使用。
7. 卸载
销毁之前加载的对象信息。
Jvm里面有一个类状态的枚举:
1. jvm类加载会加锁,防止类加载出现资源争用的情况。
通过一个案例证明一下:
public class JvmTest3 { public static void main(String[] args) { new Thread(() -> { while(true){ new AA(); } }).start(); new Thread(() -> { while(true) { new BB(); } }).start(); } } class AA{ static { System.out.println("创建AA对象"); new BB(); } } class BB{ static { System.out.println("创建BB对象"); new AA(); } }
运行结果:
执行被锁,无法继续执行。
2. Jvm加载对象属于懒加载(对象没有使用的时候,不会去加载该对象),下面通过案例说明:
public class JvmTest2 { public static void main(String[] args) { System.out.println(B.str); } } class A { static String str = "a"; static { System.out.println("static a"); } } class B extends A { static { System.out.println("static b"); } }
运行结果:
可以明显的看到B的static方法没有被执行,因为这段逻辑中,不需要是到B这个对象,哪怕B对象是A对象的子类。
Jvm 类加载是核心逻辑之一,非常重要,对一个变成人员的提升也是非常的有帮助。
标签:st3 语言 src puts 提升 内存 出现 war string
原文地址:https://www.cnblogs.com/jssj/p/14259220.html