java类的生命周期

JVM(java虚拟机)中几个比较重要的内存区域(Runtime Data Area 运行时数据区)

方法区(被所有线程共享):在java虚拟机中专门用来存放已经加载的类信息,常量,静态变量,以及方法代码的内存区域

常量池:方法区的一部分,主要用来存放创两和类中的符号引用等信息,在java8中,字符串常量池位于堆空间中

运行时常量池是常量池在运行时的表现形式,其数据不仅可以来自于class文件中的常量池,也可以是我们在程序运行时添加进来的常量

堆(被所有线程共享):存放类或数组的实例对象

栈(每一个线程都有独立的栈空间,互不干扰):方法执行的地方,里边存放的是一个一个的栈帧,每一个栈帧对应一个被调用的方法,其特点是先进后出

线程正在执行的方法位于栈顶,我们的局部变量,对象的指引都位于栈空间

栈帧中存放方法运行时的局部变量,方法出口灯,当调用一个方法时,就会在栈里边创建一个栈帧来存放这些数据

当方法调用完成,栈帧消失,如果方法中调用了其它栈帧,则继续在栈顶创建新的栈帧.

    类的生命周期

当我们编写一个java源文件后,经过编译会生成一个后缀名为class的文件,这种文件叫做字节码文件

java类的生命周期是指一个class文件从加载到卸载的全过程

一个java类的完整生命周期包括 加载,连接,初始化,使用,卸载五个阶段

  加载 

在加载阶段,虚拟机会根据类的全路径名或者直接从jar文件里读取的方式找到需要加载的类并把类的信息

加载进jvm的方法区,然后在兑取实例化一个java.lang.Class对象,作为方法区中这个类的信息的入口

  对于加载的时机,有一个原则就是,当jvm语气道有一个类将要被使用的时候,就会在它被使用之前

对这个类进行加载.加载阶段是生命周期的第一个阶段,加载阶段之后就是连接阶段,连接阶段不一定必须

在加载阶段结束后开始,但一定是加载阶段先早与连接阶段

  连接

连接阶段可以细分为 验证 准备解析3个小阶段

验证:当一个类被加载之后,必须验证这个类是否合法,这个类是不是符合字节码的格式,变量名与方法名

是否重复,数据类型是不是有效,继承与实现是不是合乎标准等,总之,这个阶段的目的就是保证加载的类

能够被jvm执行

  准备

准备阶段就是为类的静态变量分配内存并设定为jvm的默认值

对于非静态变量,则不会为它们分配内存.静态变量的初始值为jvm默认的初始值

而不是我们在程序种设定的初始值,jvm默认的初始值 基本类型为 引用类型为null

常量的值为我们在程序中设定的初值, final static int a=10,准备阶段的初值为10

  解析

把常量池的符号引用转换为直接引用

举例:在解析阶段,jvm会把show这个方法名字转换为指向方法区的一块内存地址,通过这个内存地址就可以找到

show方法具体被分配到内存中的哪一个区域了

在解析阶段,jvm会将所有的类名,接口名,方法名,字段名转换为具体的内存地址

连接阶段结束后,会根据使用情况来选择是否对类进行初始化(直接引用,被动引用)

  初始化

如果一个类被直接引用,就会触发类的初始化,在java中,直接引用

的情况有

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

  通过反射方式执行以上行为

  初始化子类的时候,会触发分类的初始化

  作为程序入口直接运行时,也就是直接调用main方法,main方法在这个类里边

除了以上四种情况,其它使用类的方式被称为类的被动引用,而被动引用不会触发类的初始化

  使用

  当使用阶段结束后,就是卸载阶段

当类使用完之后,满足下面的情况,可就会被卸载

该类所有的实例都被回收,java堆中不存在该类的任何实例

加载该类的classLoader已经被回收

该类对应的java.lang.class对象没有任何地方引用,也就是无法在任何地方通过反射访问该类的方法

3个条件全部满足,jvm就会在方法区垃圾回收时对类进行卸载,卸载过程就是在方法区中清空类信息,

java类的生命周期结束

    对比

对象是在jvm堆区创建的,在创建对象之前,会触发类加载,当类初始化完成之后,根据方法区的类信息

在兑取实例化对象,初始化非静态变量,非静态代码以及构造方法,当对象使用完之后

会在何时的时候被jvm垃圾收集器回收.

类的生命周期要比对象的生命周期长得多

 

posted @ 2018-12-06 15:02  1314520jinxuexia  阅读(146)  评论(0编辑  收藏  举报