Java程序从 .java 文件创建到程序运行要经过两大过程:
.java 源文件会被 Java编译器进行编译为.class文件:
JVM 并不是在运行时就会把所有使用到的类都加载到内存中,而是用到的时候,才加载进方法区,并且只加载一次。 Java类运行的过程大概分为两个步骤:
举例说明 Java 程序运行过程:
public class Person {
private String name;
public Person(String name){
this.name=name;
}
public void sayHello(){
System.out.println("Hello! My Name is: " + name);
}
}
public class JVMTest {
public static void main(String[] args) {
Person p=new Person("Li Ming");
p.sayHello();
}
}
首先编译 JVMTest.java 文件得到 JVMTest.class 文件,系统启动一个 JVM 进程,从 classpath 路径中找到 JVMTest.class 文件,将 JVMTest 的类信息加载到方法区中,这个过程称为 JVMTest 类的加载。
(只有类信息在方法区中,才能创建对象,使用类中的成员变量)
在 main() 方法 入口持有一个指向当前类 (JVMTest) 常量池的指针,常量池中的第一项是一个对 Person 对象的符号引用。
main 方法中 `Person p=new Person("Li Ming"),JVM 需要创建一个 Person 对象,但是此时方法区中是没有 Person 类信息的,所以 JVM 需要加载 Person 类,将 Person 类的信息加载到方法区中。
JVM 以一个直接指向方法区 Person 类的指针替换了常量池中第一项的符号引用。
加载完 Person 类的信息以后,JVM 就会在堆中为一个 Person 实例分配内存,然后调用构造方法初始化 Person 实例,并且该实例持有指向方法区中的 Person 类的类型信息(其中包括方法表)的引用。
(p 为指向该 Person 实例的引用,会被放到栈中)
执行 p.sayHello(),JVM 根据栈中 p 的引用找到 Person 对象,然后根据 Person 对象持有的引用定位到方法区中 Person 类类信息的方法表,获得 sayHello 方法的字节码地址,然后开始运行方法。