@chenxuxiong
2016-05-25T14:25:52.000000Z
字数 1668
阅读 390
JAVA虚拟机
http://www.tuicool.com/articles/QZnENv
加载-验证-准备-解析-初始化-使用-卸载
验证、准备和解析这三个部分统称为连接(linking) 。
加载、验证、准备、初始化和卸载这五个阶段的顺序是确定的,类的加载过程必须按照这种顺序按部就班的“开始”(仅仅指的是开始,而非执行或者结束,因为这些阶段通常都是互相交叉的混合进行,通常会在一个阶段执行的过程中调用或者激活另一个阶段),而解析阶段则不一定(它在某些情况下可以在初始化阶段之后再开始,这是为了支持Java语言的运行时绑定。
加载:
1、 通过一个类的全限定名来获取定义此类的二进制字节流。
2、 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
3、 在Java堆中生成一个代表这个类的java.lang.Class对象,作为方法区这些数据的访问入口。
验证是连接阶段的第一步,这一阶段的目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全
准备阶段是为类的静态变量分配内存并将其初始化为默认值,这些内存都将在方法区中进行分配。准备阶段不分配类中的实例变量的内存,实例变量将会在对象实例化时随着对象一起分配在Java堆中。
解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。
类初始化是类加载过程的最后一步,前面的类加载过程,除了在加载阶段用户应用程序可以通过自定义类加载器参与之外,其余动作完全由虚拟机主导和控制。到了初始化阶段,才真正开始执行类中定义的Java程序代码。
初始化阶段是执行类构造器()方法的过程。()方法是由编译器自动 收集类中的所有类变量的赋值动作和静态语句块(static{}块)中的语句合并产生的
主动引用
new,getstatic ,putstatic,invokestatic 4n创建类的实例,访问类的静态变量 (除常量【 被final修辞的静态变量】 ),访问类的静态方法
反射 如( Class.forName("my.xyz.Test") )
当初始化一个类时,发现其父类还未初始化,则先出发父类的初始化
虚拟机启动时,定义了main()方法的那个类先初始化
以上情况称为称对一个类进行 “主动引用” ,除此种情况之外,均不会触发类的初始化,称为 “被动引用”
被动引用
子类调用父类的静态变量,子类不会被初始化。只有父类被初始化。 也就是说对于静态字段,只有直接定义这个字段的类才会被初始化.
通过数组定义来引用类,不会触发类的初始化
访问类的常量,不会初始化类 static final
例子:
class SuperClass {
static {
System.out.println("superclass init");
}
public static int value = 123;
}
class SubClass extends SuperClass {
static {
System.out.println("subclass init");
}
}
public class Test {
public static void main(String[] args) {
System.out.println(SubClass.value);// 被动应用1
SubClass[] sca = new SubClass[10];// 被动引用2
}
}
程序运行输出 superclass init
123
从上面的输入结果证明了被动引用1与被动引用2
class ConstClass {
static {
System.out.println("ConstClass init");
}
public static final String HELLOWORLD = "hello world";
}
public class Test {
public static void main(String[] args) {
System.out.println(ConstClass.HELLOWORLD);// 调用类常量
}
}
程序输出结果
hello world
从上面的输出结果证明了被动引用3