本文是对JVM执行一个Class文件的过程的一个总结。比如,现在我有2个类:
1:Class Lava {
private int speed = 5;
void flow() {}
}
2: Class Volcano {
public static void main(String [] args) {
Lava lava = new Lava ();
lava.flow()
}
}
下面就是JVM的某个实现执行Class文件的一个过程:
1:JVM找到并读入相应的Class文件 :Volcano.class,然后把导入的二进制数据中提取的类型信息保存到方法区(方法区:保存类型信息的运行时数据区,也就是JVM内存管理体系结构的一个组成)
2:执行保存在方法区的字节码 (执行main()方法的字节码,)在执行时,持有指向Volcano类常量池的一个指针 (常量池:就是一个符号引用 如:Lava lava = new Lava()这句中的Lava就是一个符号引用)
3:JVM只在需要时才装载类(动态连接) 。JVM使用常量池指针找到第一项,发现是"Lava"字符串,检查方法区,发现Lava类并未被装载。
4:开始装载Volcano.class,同样,把读入的二进制数据中的类型信息放到方法区。
5:JVM用一个直接指向方法区Lava类数据的指针来替换常量池的第一项,也就是原先的“Lava”字符串。 这个过程就是所谓的:“常量池解析”---符号引用替换为直接引用。
6:JVM准备为新的Lava对象分配内存。分配对象当然需要类型信息,此时,用刚才替换的那个指针,也就是替换“Lava”字符串的那个指针(此时,这个指针指向方法区Lava类的数据)来访问Lava的类型信息(这个信息刚放到方法区)。找出其中记录的这样一个信息:需要分配多少内存。
7:确定内存要多大以后,在堆上分配内存,并初始化变量,包括超类的变量()。
8:把新生成的Lava对象引用压到Java栈中。到此,完成Lava lava = new Lava(); speed初始化为0。
9:通过此时生成的Lava引用,把speed 初始化为正确的值 :5
10: 通过这个引用调用Flow()。
以上为我以一个例子来说明JVM 的一个实现执行Class的流程,欢迎大家阅读和提出意见.