这个是正式为类变量分配内存并设置类变量初始值的阶段,这个变量所使用的内存都是方法区中进行分配。首先,这个时候进行内存分配的仅包括类变量(被static修饰的变量),不包括实例变量,实例变量是类加载的时候加载进堆里的。其次,这个时候的变量初始值基本都是零值,比如在定义一个变量的时候赋值了,那也是在程序编译之后,存放在类构造器的方法之中,所以要在初始化之后才会等于所赋的值,在准备阶段依然是0。
public static int value = 100;
这个时候依然是0。 也有特殊情况,在类字段的字段属性表上存在ConstantValue属性值,那么在准备阶段变量就会初始化为ConstantValue所指定的值。
public static final int value = 100;
这个阶段就会将value赋值100。
解析阶段是虚拟机将常量池中的符号引用转换为直接饮用的过程。 符号引用:符号应用是以一种符号来描述所引用的目标,符号可以是任何形式的字面量,只要在使用时能够无歧义的定位到目标即可。符号应用与虚拟机实现的内存布局无关,引用的目标不一定非要加载进内存中。各种虚拟机所实现的内存布局各不相同,但是他们能接受的符号引用必须一致,因为符号引用的字面量形式明确定义在Java虚拟机规范的class文件格式中。 直接引用:直接引用可以是直接指向目标的指针、相对偏移量、或者一个能间接定位到目标的句柄。直接引用是和虚拟机所实现的内存布局相关的,同一个符号引用在不同的虚拟机实例上翻译出来的直接引用一般不会相同,如果有了直接引用,那么引用的目标必定已经在内存中存在。 解析规则:对一个符号引用多次解析很常见,除了invokedynamic指令,虚拟机可以对第一次解析的结果进行缓存(在运行时常量池中记录直接引用,并标记为以解析的状态)从而避免解析动作的重复请求。无论是否执行的多次的解析请求,虚拟机需要保证的是在同一个实体中,如果一个符号引用已经被成功解析了,那么后续的引用解析也应该同样成功;同样,如果一个符号引用在第一次解析的时候失败了,那么在后续解析中也应该收到相同的异常。 invokedynamic指令:对于invokedynamic指令,上面的规则并不成立,当碰到某个被invokedynamic指令触发解析的符号引用时,并不意味这个解析结果对其他的invokedynamic指令也同样使用,因为invokedynamic指令的目的就是为了动态语言支持(只使用Java语言不会触发这条字节码指令),他所对应的引用称为动态调用点限定符,这里动态的含义代表必须是程序实际运行到这条指令的时候,解析动作才能进行;相反,其余可以触发解析的指令都是静态的,可以在刚刚完成加载阶段,还没有开始执行代码时进行解析。 解析动作主要是针对类或接口、字段、类方法、接口方法、方法类型、方法句柄、调用点限定符7类符号引用进行。(分别对应于常量池的CONSTANT_Class_info、CONSTANT_Fieldref_info、CONSTANT_Methodref_info、CONSTANT_InterfaceMethodref_info、CONSTANT)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。