Java方法在栈帧中的执行过程

Java方法在栈帧中的执行过程,第1张

Java方法在栈帧中的执行过程 Java方法的字节码结构

以如下代码为例,对 Java 方法的字节码结构进行阐述(jdk 版本 1.8.0_301)。

package com.zero.demo;

public class MethodAnalyzeDemo {

    public int doSomething(int i, int j) {
        int result = i + j;
        return result;
    }
}

通过 javac 命令,可以对 .java 文件进行编译,将源代码编译成字节码,即生成 .class 文件。

javac MethodAnalyzeDemo.java

通过 javap -verbose 命令,将会根据 .class 文件的字节码,打印出 Java 类中方法的字节码信息。

PS C:UsersZeroDesktopdemo> javap -verbose .MethodAnalyzeDemo.class
Classfile /C:/Users/Zero/Desktop/demo/MethodAnalyzeDemo.class
  Last modified 2021-12-26; size 292 bytes
  MD5 checksum ee74d225ac594d1577a0005f2106072d
  Compiled from "MethodAnalyzeDemo.java"
public class com.zero.demo.MethodAnalyzeDemo
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #3.#12         // java/lang/Object."":()V
   #2 = Class              #13            // com/zero/demo/MethodAnalyzeDemo
   #3 = Class              #14            // java/lang/Object
   #4 = Utf8               
   #5 = Utf8               ()V
   #6 = Utf8               Code
   #7 = Utf8               LineNumberTable
   #8 = Utf8               doSomething
   #9 = Utf8               (II)I
  #10 = Utf8               SourceFile
  #11 = Utf8               MethodAnalyzeDemo.java
  #12 = NameAndType        #4:#5          // "":()V
  #13 = Utf8               com/zero/demo/MethodAnalyzeDemo
  #14 = Utf8               java/lang/Object
{
  public com.zero.demo.MethodAnalyzeDemo();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."":()V
         4: return
      LineNumberTable:
        line 3: 0

  public int doSomething(int, int);
    descriptor: (II)I
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=4, args_size=3
         0: iload_1
         1: iload_2
         2: iadd
         3: istore_3
         4: iload_3
         5: ireturn
      LineNumberTable:
        line 6: 0
        line 7: 4
}
SourceFile: "MethodAnalyzeDemo.java"

其中,关于 doSomething() 方法的字节码信息,如下图所示:

图1

在 JVM 中,一个线程为一个栈,一个栈由多个栈桢组成,一个栈桢对应一个方法。

因此,doSomething() 方法在栈帧中的结构,如下图所示:

图2

接下来,对 doSomething() 方法的每个部分进行讲述。

descriptor: (II)I
descriptor: (II)I

descriptor 表示方法的描述,(II) 表示 doSomething() 方法有两个 int 类型的形参,I 表示方法的返回值是 int 类型。

flags: ACC_PUBLIC
flags: ACC_PUBLIC

flags 表示方法的访问标志,ACC_PUBLIC 表示 doSomething() 方法的访问标志为 public。

Code
Code:
  stack=2, locals=4, args_size=3
     0: iload_1
     1: iload_2
     2: iadd
     3: istore_3
     4: iload_3
     5: ireturn
  LineNumberTable:
    line 6: 0
    line 7: 4

Code 是方法表,表示 Java 方法经过编译后的字节码指令,就是以字节码的形式表达 Java 方法的执行过程。

stack=2, locals=4, args_size=3

表示方法在栈帧的基本信息,具体说明如下所示。

  • stack

*** 作数栈的深度

  • locals

局部变量表的大小

  • args_size

方法形参的数量,例如 doSomething() 方法的 args_size:

args_size = 3 = int i + int j + 对象实例的引用

对象实例的引用,可以理解为,通过 this 关键字访问此方法所属的对象。

举个例子,我们日常开发中经常使用到的 this.i = i;

public class Demo {
    int i;
    public setI(int i) {
        this.i = i;
    }
}

0: iload_1 …… 5: ireturn

表示方法执行的指令,就是 int result = i + j; 和 return result; 这两行代码对应的指令。

  • 0: iload_1

将局部变量表中第二个变量(i)加载到 *** 作数栈,这个变量是 int 类型。

  • 1: iload_2

将局部变量表中第三个变量(j)加载到 *** 作数栈,这个变量是 int 类型。

  • 2: iadd

将 *** 作数栈中栈顶的两个 int 类型变量(i,j)出栈,把它们相加的结果加载到栈顶(i + j)。

  • 3: istore_3

将 *** 作数栈中栈顶的 int 类型变量(就是 iadd 的结果)进行出栈,并且赋值局部变量表的第四个变量(result)。

  • 4: iload_3

将局部变量表中第四个变量(result)加载到 *** 作数栈,这个变量是 int 类型。

  • 5: ireturn

将 *** 作数栈中栈顶的 int 类型变量(result)返回。

0: iload_1 …… 5: ireturn 的执行过程,如下图所示:

图3

为什么没有 iload_0 ?

因为,构造方法或实例方法(非静态方法),对象实例的引用(this)会存放在索引为 0 的位置,其余参数按照参数表顺序进行排列。

而且,如果方法修改为如下所示,那么 0: iload_1 就会变成 0: iload_2,因为 String str 位于局部变量表索引为 1 的位置,int i 位于局部变量表索引为 2 的位置。


LineNumberTable

表示 java 源代码(.java文件)的行号和字节码(.class文件)的行号之间的对应关系,主要是方便在异常发生的时候,在堆栈中显示出源代码出错的行号;以及在调试过程中,按照源代码的行号设置断点。

LineNumberTable 不是运行时必需的属性,通过 -g:none 参数取消,-g:lines 参数生成(默认)。

line 6: 0、line 7: 4 的含义,如下图所示:

图4

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5684112.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存