JVM系列(1)-变量

jovisoft 2019-06-21

前言

这段时间一直在看JVM相关的书籍,虽然有点难,至少到目前为止还没有放弃。写这篇文章的目的:当做自己这段时间学习的小回顾。本章主要通过几个代码片段,分析下局部变量表与操作数栈之间的数据传递关系,重点讲解iload,istore,iconst_<n>,iadd命令

提前了解

JVM的几个概念

  • 局部变量表:每个栈帧内部都包含一组称为局部变量表的变量列表

  • 操作数栈:每个栈帧内部都包含一个操作数栈

  • iconst_0:把int型的0值压入操作数栈

  • iload:将一个局部变量加载到操作数栈上

  • istore:将一个数值从操作数栈上存储到局部变量表中

  • iadd:返回栈顶的两个元素做加法运算,并加结果压栈

如何使用dos查看字节码文件

首先通过dos进入TestApp.class所在的目录,然后运行命令javap -c TestApp,即可看到编译后的字节码文件

程序片段一

  • 以下是一个java源代码

public void test1(){      
    int c=0;              
}
  • 编译后的字节码

public void test1();
    Code:
       0: iconst_0
       1: istore_1
       2: return
  • 代码分析

因为test1()是一个实例方法,所以在局部变量表中,索引为0的位置会保存该方法所在类的引用(this),所以才会出现istore_1而不是istore_0

我们对int c = 0做下拆解,一个常量0,一个变量c。

0: iconst_0   //将常量0压入操作数栈
1: istore_1   //将栈顶出栈,即c=0
2: return      //因为是void,没有返回值

程序片段二

  • Java源代码如下

public static void test2(){    
    int c=0;                   
}
  • 编译后的字节码文件

public static void test2();
    Code:
       0: iconst_0
       1: istore_0
       2: return
  • 分析

因为test2()是一个静态的方法,不会在局部变量表中插入任何数据。所以你看到的是istore_0而不是像程序片段一中的istore_1。其他分析跟程序片段一相同

程序片段三

  • java源代码

public int test3(){         
    int c=0;                
    return c;               
}
  • 编译后的字节码

public int test3();
    Code:
       0: iconst_0
       1: istore_1
       2: iload_1
       3: ireturn
  • 分析

0: iconst_0        //将常量0压栈
1: istore_1     //将栈顶出栈,及c=0
2: iload_1      //将变量c压入栈顶
3: ireturn        //返回栈定元素

程序片段四

  • Java源代码

public int test4(int a,int b){       
    int c=0;                         
    return a+b;                      
}
  • 编译后的字节码

public int test4(int, int);
    Code:
       0: iconst_0
       1: istore_3
       2: iload_1
       3: iload_2
       4: iadd
       5: ireturn

** 分析

因为test4(int a,int b)是实例方法,所以在局部变量表索引为0的位置会插入this
因为test4(int a,int b)带有两个参数,所以在局部变量索引索引为1的位置插入a,在索引为2的位置插入b。

0: iconst_0        //将常量0压栈
1: istore_3        //将栈顶出栈,即c=0,将c存储到局部变量表索引为3的位置
2: iload_1        //将局部变量表中索引为1的变量压栈,即a压栈
3: iload_2        //将局部变量表中索引为2的变量压栈,即b压栈
4: iadd            //将栈顶两个元素出栈,做加法,然后把结果再入栈(即a,b出栈,将a+b入栈)
5: ireturn        //返回a+b的值

程序片段五

  • java源代码

public int test5(int a,int b){    
    int c=0;                      
    c= a+b;                       
    return c;                     
}
  • 编译后的字节码

public int test5(int, int);
    Code:
       0: iconst_0
       1: istore_3
       2: iload_1
       3: iload_2
       4: iadd
       5: istore_3
       6: iload_3
       7: ireturn
  • 分析

0: iconst_0        //将常量0压栈
1: istore_3        //将栈顶出栈,及c=0
2: iload_1        //从局部变量表中加载索引为1的变量压栈,即a压栈
3: iload_2        //从局部变量表中加载索引为2的变量压栈,即b压栈
4: iadd            //将栈顶两个元素出栈,做加法,然后将结果压栈,及a+b压栈
5: istore_3        //将栈顶元素出栈,并保存到局部变量表中,即c=a+b
6: iload_3        //从局部变量表中加载索引为3的变量压栈,即c压栈
7: ireturn        //返回栈顶元素,即返回c

相关推荐