JavaKeeper:JVM类加载子系统解毒( 二 )


为类变量分配内存并且设置该类变量的默认初始值 , 即零值数据类型零值int0long0Lshort(short)0char'\ 'byte(byte)0booleanfalsefloat0.0fdouble0.0dreferencenull
这里不包含用final修饰的static , 因为final在编译的时候就会分配了 , 准备阶段会显示初始化
这里不会为实例变量分配初始化 , 类变量会分配在方法区中 , 而实例变量是会随着对象一起分配到Java堆中private static int i = 1; //变量i在准备阶只会被赋值为0 , 初始化时才会被赋值为1 private final static int j = 2; //这里被final修饰的变量j , 直接成为常量 , 编译时就会被分配为2解析(Resolve)
将常量池内的符号引用转换为直接引用的过程
事实上 , 解析操作往往会伴随着JVM在执行完初始化之后再执行
符号引用就是一组符号来描述所引用的目标 。 符号引用的字面量形式明确定义在《Java虚拟机规范》的Class文件格式中 。 直接引用就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄
解析动作主要针对类或接口、字段、类方法、接口方法、方法类型等 。 对应常量池中的CONSTANT_Class_info、CONSTANT_Fieldref_info、CONSTANT_Methodref_info等3. 初始化(Initialization)
初始化阶段就是执行类构造器方法()的过程
此方法不需要定义 , 是javac编译器自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并而来
构造器方法中指令按语句在源文件中出现的顺序执行
()不同于类的构造器(构造器是虚拟机视角下的
())
若该类具有父类 , JVM会保证子类的
()执行前 , 父类的
()已经执行完毕
虚拟机必须保证一个类的
()方法在多线程下被同步加锁public class ClassInitTest{private static int num1 = 30;static{num1 = 10;num2 = 10;//num2写在定义变量之前 , 为什么不会报错呢??System.out.println(num2);//這裡直接打印可以吗?报错 , 非法的前向引用 , 可以赋值 , 但不可调用}private static int num2 = 20;//num2在准备阶段就被设置了默认初始值0 , 初始化阶段又将10改为20public static void main(String[] args){System.out.println(num1);//10System.out.println(num2);//20} }类的主动使用和被动使用
Java程序对类的使用方式分为:主动使用和被动使用 。 虚拟机规范规定有且只有5种情况必须立即对类进行“初始化” , 即类的主动使用 。
创建类的实例、访问某个类或接口的静态变量 , 或者对该静态变量赋值、调用类的静态方法(即遇到new、getstatic、putstatic、invokestatic这四条字节码指令时)
反射
初始化一个类的子类
Java虚拟机启动时被标明为启动类的类
JDK7 开始提供的动态语言支持:java.lang.invoke.MethodHandle实例的解析结果 , REF_getStatic、REF_putStatic、REF_invokeStatic句柄对应的类没有初始化 , 则初始化
除以上五种情况 , 其他使用Java类的方式被看作是对类的被动使用 , 都不会导致类的初始化 。 eg:public class NotInitialization {public static void main(String[] args) {//只输出SupperClass int 123,不会输出SubClass init//对于静态字段 , 只有直接定义这个字段的类才会被初始化System.out.println(SubClass.value);} } class SuperClass {static {System.out.println("SupperClass init");}public static int value = http://news.hoteastday.com/a/123; } class SubClass extends SuperClass {static {System.out.println("SubClass init");} }类加载器
JVM支持两种类型的类加载器 , 分别为引导类加载器(Bootstrap ClassLoader)和自定义类加载器(User-Defined ClassLoader)
从概念上来讲 , 自定义类加载器一般指的是程序中由开发人员自定义的一类类加载器 , 但是Java虚拟机规范却没有这么定义 , 而是将所有派生于抽象类ClassLoader的类加载器都划分为自定义类加载器启动类加载器(引导类加载器 , Bootstrap ClassLoader)


推荐阅读