JVM知识(三)---类的执行机制(上)

来源:互联网 发布:windows掌上电脑 编辑:程序博客网 时间:2024/06/05 17:13

JVM完成类的加载并产生Class对象以后,就可以执行Class对象的静态方法或者实例化对象调用其方法。JVM在源码编译阶段将源码编译为JVM字节码,JVM字节码是一种中间代码,JVM会在运行期执行该中间代码,这种方式成为字节码的解释执行方式。
字节码的解释执行:
如下我们写出这样一个简单的类文件:

public class Demo {public void execute() {Teacher.teach();Teacher teacher = new Teacher();teacher.run();People student = new Student();student.run();}}interface People {public int run();}class Teacher {public static int teach() {return 1 + 2;}public int run () {return 1+2;}}class Student implements People {public int run () {return 1 + 2;}}


使用命令javac Demo.java编译上面的类,然后使用javap -c Demo查看该类方法execute方法生成的字节码文件如下:

public void execute();  Code:   0:   invokestatic    #2; //Method Teacher.teach:()I   3:   pop   4:   new     #3; //class Teacher   7:   dup   8:   invokespecial   #4; //Method Teacher."<init>":()V   11:  astore_1   12:  aload_1   13:  invokevirtual   #5; //Method Teacher.run:()I   16:  pop   17:  new     #6; //class Student   20:  dup   21:  invokespecial   #7; //Method Student."<init>":()V   24:  astore_2   25:  aload_2   26:  invokeinterface #8,  1; //InterfaceMethod People.run:()I   31:  pop   32:  return}
JVM采用四种指令来执行不同的方法调用:invokestatic调用static方法,invokevirtual调用对象实例方法,invokeinteface调用的是接口方法,invokespecial调用的是private方法和编译源码后生成的init方法,如构造方法。

SUN JDK基于stack的体系结构来执行字节码,基于stack能是代码更加紧凑,体积更小。stack的系统结构如下图:


线程在创建后都会产生pc registers和stack;pc存放了下一条将要执行的指令在方法内的偏移量;stack中存放了StackFrame,每个方法每次调用都会产生StackFrame,StackFrame又主要分为局部变量区和操作数栈,局部变量区主要存放方法中的局部变量和参数,操作数栈主要存放方法在执行过程中产生的中间变量;下面我们具体来看一段代码的执行指令:代码很简单,如下:

public class Demo {public static void execute() {int a = 1;int b = 2;int c = (a + b) * 4;  }}
以下为该类的完成字节码:

public class Demo extends java.lang.Object{public Demo();  Code:   0:   aload_0   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V   4:   returnpublic static void execute();  Code:   0:   iconst_1           // 将类型为int,值为1的常量放入操作数栈中   1:   istore_0   //将操作数栈中栈顶的值放入局部变量区   2:   iconst_2   //将类型为int,值为2的常量放入操作数栈中   3:   istore_1   //将操作数栈栈顶的值放入局部变量区   4:   iload_0   //装载局部变量区的第一个值到操作数栈   5:   iload_1   //装载局部变量区的第二个值到操作数栈   6:   iadd   //执行int整数的加法操作,并将结果存入操作数栈中   7:   iconst_4   //将类型为int,值为4的常量放入操作数栈中   8:   imul   //执行乘法操作,并将结果存入操作数栈中   9:   istore_2   //将操作数栈中栈顶的值存入局部变量区   10:  return   //返回}


我们主要看该execute方法下的code,指令的解释详见指令后面的注释。

     

原创粉丝点击