Introduction to common bytecode instructions in Android

problem background

In the process of Android development, it is often necessary to understand the operation mechanism of the compiled java code by looking at the bytecode corresponding to the java code. This article will introduce some basic bytecode instructions through a simple demo.

problem analysis

For example the following code:

public class test {
    public static void main(String[] args) {
        int a = 100;
        int b = 100;
        int c = 100;
        a += b + c;
        System.out.println(a);
    }
}

The result of the operation is as follows:
operation result

a += b + c <==> a += (b + c), check the corresponding bytecode file as follows:

// class version 52.0 (52)
// access flags 0x21
public class test {

  // compiled from: test.java

  // access flags 0x1
  public <init>()V
   L0
    LINENUMBER 1 L0
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
    RETURN
   L1
    LOCALVARIABLE this Ltest; L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x9
  public static main([Ljava/lang/String;)V
   L0
    LINENUMBER 3 L0
    BIPUSH 100
    ISTORE 1 // 将100存储到局部变量
   L1
    LINENUMBER 4 L1
    BIPUSH 100
    ISTORE 2 // 将100存储到局部变量
   L2
    LINENUMBER 5 L2
    BIPUSH 100
    ISTORE 3 // 将100存储到局部变量
   L3
    LINENUMBER 6 L3
    ILOAD 1 // 从局部变量表中加载 int 类型到操作数栈
    ILOAD 2 // 从局部变量表中加载 int 类型到操作数栈
    ILOAD 3 // 从局部变量表中加载 int 类型到操作数栈
    IADD // 将栈顶两个 int 类型数值相加
    IADD // 将栈顶两个 int 类型数值相加
    ISTORE 1 // 将 int 类型存储到局部变量中,这里就是把结果存储到第一个变量
   L4
    LINENUMBER 7 L4
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    ILOAD 1
    INVOKEVIRTUAL java/io/PrintStream.println (I)V
   L5
    LINENUMBER 8 L5
    RETURN
   L6
    LOCALVARIABLE args [Ljava/lang/String; L0 L6 0
    LOCALVARIABLE a I L1 L6 1
    LOCALVARIABLE b I L2 L6 2
    LOCALVARIABLE c I L3 L6 3
    MAXSTACK = 3
    MAXLOCALS = 4
}

conclusion of issue

By viewing the bytecode corresponding to the java code, you can clearly see the execution process of the compiled java code. In Android development, it is very necessary to understand bytecode knowledge. At critical moments, we can look at the bytecode to answer some doubts. The following are some common bytecode instructions:

1. 加载和存储指令:

aload:从局部变量表中加载引用类型到操作数栈。

astore:将引用类型存储到局部变量表中。

iload:从局部变量表中加载 int 类型到操作数栈。

istore:将 int 类型存储到局部变量表中。

fload:从局部变量表中加载 float 类型到操作数栈。

fstore:将 float 类型存储到局部变量表中。



2. 算术和逻辑指令:

iadd:将栈顶两个 int 类型数值相加。

isub:将栈顶两个 int 类型数值相减。

imul:将栈顶两个 int 类型数值相乘。

idiv:将栈顶两个 int 类型数值相除。

iand:将栈顶两个 int 类型数值进行按位与操作。

ior:将栈顶两个 int 类型数值进行按位或操作。



3. 类型转换指令:

i2l:将 int 类型转换为 long 类型。

l2i:将 long 类型转换为 int 类型。

f2d:将 float 类型转换为 double 类型。

d2i:将 double 类型转换为 int 类型。



4. 控制流指令:

if_icmpeq:如果两个 int 类型数值相等,则跳转到指定位置。

goto:无条件跳转到指定位置。

tableswitch:根据索引值跳转到不同位置的指令。



5. 方法调用和返回指令:

invokevirtual:调用实例方法。

invokestatic:调用静态方法。

invokeinterface:调用接口方法。

ireturn:从方法中返回 int 类型值。

invokedynamic: 运行时动态解析并绑定方法调用

Continuously updated, interested partners can further in-depth research.

Guess you like

Origin blog.csdn.net/weixin_39033300/article/details/132227205