深入JVM学习笔记 类型生命周期
Java Class文件
1、Class文件中的内容结构列表
--magic(魔数) OXCAFEBABE 用于区分JAVA Class文件和非JAVA Class文件
--minor version/major version 用于检测Class文件版本号是否属于JVM可以处理的范围
--constant pool count/constant pool 常量池
--access flags 访问标志
--this class 当前类的一个对常量池的索引
--super class 超类
--interfaces count/interfaces 所实现接口
--fields count/fields 字段信息
--methods count/methods 方法信息
--attributes count/attributes 属性信息
2、Java数组最多有255维
类型的生命周期
3、动态连接阶段:验证(数据是否合法),准备(为类分配内存),解析(符号引用转为直接引用,可选操作)
任何类的初始化都要求他所有它的祖先类(而非祖先接口)预先初始化,而一个接口的初始化并不需要它所有的祖先接口预先初始化。只有在某个接口所声明的非常量字段被使用时,该接口才会被初始化。
4、Java编译器把类变量初始化语句和静态初始化语句的代码都放到class文件的<clinit>()方法中,顺序就按照它们在类或者接口中声明的顺序。
并非所有的类都需要在它们的class文件中拥有一个<clinit>()方法。如果类没有声明类变量也没有静态初始化语句,那么它就不会有<clinit>()方法。如果类声明了类变量,但是没有明确使用类变量初始化语句或者静态初始化语句初始化它们,那么类不会有<clinit>()方法。如果类仅包含静态final变量的类变量初始化语句,而且这些类变量初始化语句采用编译时常量表达式,类也不会有<clinit>()方法。只有那些的确需要执行Java代码来赋予类变量正确初始值的类才会有类初始化方法。
例如:
class Example{ static final int angle = 35; static final int length = angle * 2; }class NewParent{ static int hoursOfSleep = (int)(Math.random()*3.0); static{ System.out.println("NewParent was initiaized"); } } NewBornBady extends NewParent{ static int hoursOfCrying = 6 + (int)(Math.random()*2.0); static{ System.out.println("NewBornBady was initialized"); } } class Example{ public static void main(String[] args){ int hours = NewBornBady.hoursOfSleep; System.out.println(hours); } static{ System.out.println("Example was initialized"); } }