JAVA类生命周期
一个Java类在被编译器编译成字节码文件(.Class文件)后,Java虚拟机会将它加载到内存中,最后将其卸载出内存,这是整个Java类的生命周期。整个生命周期可分为加载、验证、准备、解析、初始化、使用、卸载这七个阶段,其中验证、准备和解析,统称为连接阶段,前五步是类加载阶段,如下图所示:
下面详细介绍类加载阶段的各个步骤所做的工作:
- 加载(Loading): 这里需要注意的是“加载”与“类加载”是两个不同的概念,“加载”只是“类加载”的其中一个阶段,“加载”过程主要获取类编译后的二进制字节流,将类的静态信息放置在方法区。生成的java.lang.Class对象放置在堆中。
- 验证(Verification):验证是连接的第一步,做了文件格式验证、元数据验证和字节码验证等,主要保证字节流中信息符合《Java虚拟机规范》,防止恶意代码攻击。
- 准备(Preparation):给类中定义的变量(即静态变量)分配内存空间,并赋默认值(0值),这里只包括类变量不包括对象变量。
- 解析(Resolution):将常量池中的符号引用转为直接引用,那么什么是符号引用呢?通俗点说,当虚拟机在对A进行类加载时,由于A类加载过程中涉及B类,此时虚拟机并不知道B类的地址,用一个字符串表示它的地址。这个字符串为符号引用,实际的地址为直接引用。
- 初始化(Initialization):将用户给类变量赋值操作,完成初始化工作,这个部分一般由用户主导。初始化阶段就是执行类构造器方法< clinit >()的过程。此方法不需要定义,是javac编译器自动收集类中的所有类变量的赋值动作和静态代码快中的语句合并而来。若该类具有父类,Jvm会保证子类的< clinit >() 执行前,父类的< clinit >() 已经执行完成。
使用(Using):任何一个数据类型在使用之前都需要经过加载、链接、初始化3个类加载过程。类经过类加载过程后,开发者可以调用它的静态类成员或者使用new关键字创建对象实例。
卸载(Unloading): 当类同时满足三个条件时,这个类的生命周期就结束了,会被卸载。这三个条件是:
- 该类的所有实例都已经被回收,也就是java堆中不存在该类的任何实例。
- 加载该类的ClassLoader已经被回收。
- 该类对应的java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射访问该类。