Android の一般的なバイトコード命令の概要

問題の背景

Android 開発の過程では、コンパイルされた Java コードに対応するバイトコードを見て、その動作の仕組みを理解する必要があることがよくありますが、この記事では、簡単なデモを通して、バイトコードの基本的な命令をいくつか紹介します。

問題分析

たとえば、次のコード:

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);
    }
}

操作の結果は次のようになります。
演算結果

a += b + c <==> a += (b + c) の場合は、次のように対応するバイトコード ファイルを確認します。

// 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
}

問題の結論

Java コードに対応するバイトコードを表示すると、コンパイルされた Java コードの実行プロセスが明確にわかります。Android 開発では、バイトコードの知識を理解することが非常に必要です。重要な瞬間には、バイトコードを調べていくつかの疑問に答えることができます。一般的なバイトコード命令の一部を次に示します。

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: 运行时动态解析并绑定方法调用

継続的に更新され、関心のあるパートナーはさらに詳細な調査を行うことができます。

おすすめ

転載: blog.csdn.net/weixin_39033300/article/details/132227205