类的生命周期:
简介java虚拟机的作用:java虚拟机为java程序提供运行时环境,其中一个重要的任务就是管理类和对象的生命周期,类的生命周期从类被加载、连接和初始化开始,到类被卸载结束。当类处于生命周期时,它的二进制数据位于方法区内,在堆区中还有一个描述该类的Class对象。只有当类处于生命周期中时,java程序才能使用它,比如调用类的静态变量,静态方法和创建类的实例。
java虚拟机加载某个类过程:
1、加载:查找并加载类的二进制数据
2、连接:包括验证、准备和解析类的二进制数据
a、验证:确保加载类的正确性
b、准备:为类的静态变量分配内存并将其初始化为默认值
c、解析:把类的符号应用转换为直接应用
3、初始化:为类的静态变量赋予正确的初始值
加载详解:
类的加载是把类的.class文件中的二进制数据读入到内存中,把它放到运行时数据区的方法区内,然后在堆区创建一个java.lang.class对象,用类封装类在方法区内的数据结构。
类的加载的最终产品时位于运行时数据区内的堆区的class对象。class对象封装了类在方法区内的数据结构,并且向java程序提供了访问类在方法区内的数据结构的接口。
类的加载是由类的加载器完成的,类的加载器分为两种:
一是:java虚拟机自带的加载器,包括启动类加载器、拓展类加载器、系统类加载器。
二是:用户自定义的类的加载器,是java.lang.ClassLoader类的子类的实例,用户可以通过定制它来定制类的加载方式。
类的验证:
当类被加载后,就进入到连接阶段。连接就是把已经读入到内存中的类的二进制数据合并到虚拟机的运行时环境中去。
类的验证包括如下内容:
1、类文件的结构检查:确保类文件遵从java类文件的固定格式
2、语义检查:确保类本身符合java语言的语法规定,比如final修饰的类有没有子类,final修饰的方法有没有被覆盖等等
3、字节码检查:确保字节码流可以被java虚拟机安全的执行
4、二进制兼容验证:确保相互应用类之间的协调一致
类的准备:
在准备阶段,java虚拟机为类的静态变量分配内存,并赋予默认初始值。
类的解析:
在类的解析阶段,java虚拟机把类中的二进制数据中的符号引用替代为直接引用
类的初始化:
在初始化阶段,java虚拟机执行类的初始化语句,为类的静态变量赋予初始值。
静态变量的初始化有两种方式:一种是在声明时初始化,另一种是在静态代码块中初始化。
java虚拟机初始化一个类包含以下步骤:
a、加入这个类还没有被加载和连接,那就先进性加载和连接。
b、加入这个类存在直接父类,并且这个父类还没有被初始化,那就先初始化直接父类。
c、加入类中很有初始化语句,那就依次执行这些初始化语句。
类的初始化时机:
如下六种活动被看做程序对类或接口的主动使用:
a、创建类的实例。包括new关键字创建,通过反射、克隆创建
b、调用类的静态方法
c、访问某个类或接口的静态变量,或给这些静态变量赋值。
d、调用java api中的某些反射方法
e、初始化一个类的子类。
f、java虚拟机启动时被标明为启动类的类
特殊情况:
a、对于final的静态常量,如果在编译时能够计算出变量的取值,那么使用该静态常量不会导致类的初始化。
b、对于final的静态常量,如果在编译时不能够计算出变量的取值,那么使用该静态常量会导致类的初始化。
c、当java虚拟机初始化一个类时,要求他的所有父类已经被初始化,但这条规则不适用于接口