JVM内存模型如上图所示.但是运行时方法在java代码运行时是如何运转的呢.下面我们通过一个简单的代码来看看运行时方法区的各个模块是如何运转的
package com.bonc.jvm;
/**
* @Classname JVMTest
* @Description TODO
* @Date 2020/6/14 10:54
* @Created by sz
*/
public class JVMTest {
public static User user = new User();
private final static int initData=1111;
public int computer(){
int a =1;
int b= 2;
int c=(a+b)*15;
return c;
}
public static void main(String[] args) {
JVMTest jvmTest =new JVMTest();
int computer = jvmTest.computer();
System.out.println(computer);
}
}
通过java自带的javap -c命令可以查看编译完,我们稍微可以理解的代码
Compiled from "JVMTest.java"
public class com.bonc.jvm.JVMTest {
public static com.bonc.jvm.User user;
public com.bonc.jvm.JVMTest();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public int computer();
Code:
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: iadd
7: bipush 15
9: imul
10: istore_3
11: iload_3
12: ireturn
public static void main(java.lang.String[]);
Code:
0: new #2 // class com/bonc/jvm/JVMTest
3: dup
4: invokespecial #3 // Method "<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #4 // Method computer:()I
12: istore_2
13: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
16: iload_2
17: invokevirtual #6 // Method java/io/PrintStream.println:(I)V
20: return
static {
};
Code:
0: new #7 // class com/bonc/jvm/User
3: dup
4: invokespecial #8 // Method com/bonc/jvm/User."<init>":()V
7: putstatic #9 // Field user:Lcom/bonc/jvm/User;
10: return
}
java 虚拟机运行一个线程会给当前线程分配一个栈空间.栈空间是有许多栈帧组成.每执行一个方法会给单前方法分配一个栈帧空间.栈帧空间有局部变量表,操作数栈,动态链接,方法出口.操作数栈:是指方法执行时临时存放操作数的内存空间.
我们先看一下方法computer的反汇编代码
执行完第一个反汇编代码.查看操作手册代码 JVM指令手册下载地址:传送门
执行完computer内存空间为
执行完istore_1 查看手册这里的局部变量1值得是局部变量表中第一个局部变量.也就是a
所以执行完这几行代码的结果为
下面的 2: iconst_2 3: istore_2 这两行代码执行完之后内存空间的
下面执行iload_1查指令手册
将局部变量表局部变量1放入操作数栈中
同理执行iload_2 将局部变量表局部变量2放入操作数栈中
所以至此jvm内存空间中的东西变成
执行6: iadd 查指令手册 执行int类型的加法
将操作数栈中的变量拿到cpu中做加法算法,将执行结果重新压回操作数栈中
所以执行结果为
执行下一步bipush 15 查指令手册
也就是将15压入操作数栈中
接下来执行imul 查指令手册
也就是将操作数栈中的数字拿到cpu中执行乘法,执行结果返回到操作数栈中
下面一步执行istore_3 和前面将操作数栈中的值45存入局部变量3中
再接着执行iload_3 查指令手册
讲局部变量表中局部变量3的数值加载到操作数栈中
再执行ireturn
将操作数栈中的值.作为方法返回值返回