类的生命周期

1.JVM内存划分:堆,栈,方法区,本地方法栈,程序计数器(与生命周期关系不大)。

2.方法区:专门用来存放已经加载的类信息、常量、静态变量以及方法代码的内存区域。常量池是方法区的一部分,主要用来存放常量和类中的符号引用等信息。

3.堆区:存放类的实例,即对象。new xxx()一般存放在这里。

4.栈区:由一个一个的栈帧组成的后进先出的栈式结构。栈中存放方法运行时产生的局部变量、方法出口等信息。当调用一个方法时,栈中就会创建一个栈帧存放这些数据,当方法调用完成时,栈帧消失。如果方法中调用了其他方法,则继续在栈顶创建新的栈桢。

5.类的生命周期:在编写完程序的源代码后,需要先编译成.class文件,也就是字节码文件,只有字节码文件才可以在JVM中运行。所以类的生命周期一般指.class文件从加载到卸载的全过程。

 

 

 6.加载:这个加载和类加载不是一回事。类加载包含了类的生命周期中加载、连接、初始化这三个阶段。在加载阶段,JVM会找到需要加载的类,把类的信息(属性和方法等)存到方法区中,然后在堆中实例化一个java.lang.class对象,作为方法区中这个类信息的入口。最常用的加载方式有两种,一种是根据类的全路径名找到相应的class文件,然后从class文件中读取文件内容;另一种是从jar文件中读取。

7.何时加载:当JVM预感某个类将要被使用时,就会在使用它之前对这个类进行加载。比如说,在一段代码中出现了一个类的名字,JVM在执行这段代码之前并不能确定这个类是否会被使用到,于是,有些JVM会在执行前就加载这个类,而有些则在真正需要用的时候才会去加载它,这取决于具体的JVM实现。(单例模式)

8.连接:做一些加载后的验证工作以及一些初始化前的准备工作,可以细分为三个步骤:验证、准备和解析。连接阶段并不会等加载阶段完全完成之后才开始,而是交叉进行,可能一个类只加载了一部分之后,连接阶段就已经开始了。加载阶段总是在连接阶段之前开始,连接阶段总是在加载阶段完成之后完成。

9.验证:当一个类被加载之后,必须要验证一下这个类是否符合语法。

10.准备:为类的静态变量分配内存并且赋予JVM的默认初值,不是我们程序中设定的值。对非静态的变量,不会为它们分配内存。JVM默认的初值是这样的:

    1)基本类型(int、long、short、char、byte、boolean、float、double)的默认值为0。

    2)引用类型的默认值为null。

    3)常量的默认值为我们程序中设定的值,比如我们在程序中定义final static int a = 100,则准备阶段中a的初值就是100。

11.解析:在解析阶段,JVM会将所有的类或接口名、字段名、方法名转换为具体的内存地址。通过内存地址,可以找到存储在内存空间里的信息。

12.初始化:如果一个类被直接引用,就会触发类的初始化。直接引用的情况有:

     1)通过new关键字实例化对象、读取或者设置类的静态变量,调用类的静态方法。

     2)通过反射执行以上三种行为。

     3)初始化子类的时候会触发父类的初始化。

     4)直接调用Main方法。

除了上述四种方式,其他使用类的方式叫被动引用,被动引用不会触发类的初始化。

在类的初始化阶段,只会初始化与类相关的静态赋值语句和静态语句,也就是有static关键字修饰的信息,而没有static修饰的赋值语句和执行语句在实例化对象的时候才会运行。

13.卸载:在类使用完之后,满足以下条件类会被卸载。

     1)该类的所有实例化对象都被回收,在堆中不存在该类的任何实例。

     2)加载该类的ClassLoader已经被回收。

     3)该类对应的java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法。

如果以上三个条件全部满足,JVM就会在方法区垃圾回收的时候对类进行卸载,类的卸载过程其实就是在方法区中清空类信息,类的整个生命周期就结束了。

posted @ 2022-05-13 08:59  lc2100222  阅读(111)  评论(0)    收藏  举报