0%

class字节码解析工具

https://github.com/JuneLeo/class-parse
解析程度:比 editor Class.bt 要解析的更深,同javap解析一样。
属性表也已经全部解析完毕
https://github.com/JuneLeo/class-parse/tree/master/src/main/java/org/example/bytecode/parse/attribute

原理

根据class字节码的组成,分段解析class字节码,依此逐个解析;Parse中pase方法传入解析开始位置索引;返回结束位置索引

1
2
3
public interface Parse {
int parse(int start, byte[] code);
}
  • code:为class字节码
  • start:字节码开始位置
  • return:下一个开始解析的位置
    1
    2
    3
    4
    5
    6
    public void parse(byte[] bytes) {
    int start = 0;
    for (Parse pars : parses) { // parses为解析器集合
    start = pars.parse(start, bytes);
    }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// magic 
MagicParse{magic='CAFEBABE'}
// minor major
VersionParse{minor=0, major=52}
// 常量池
ConstantPoolParse{constantPoolCount=49, constantParse=ConstantMethodRefInfoParse{classIndex=10, nameAndTypeIndex=27, tag=10, name=CONSTANT_Methodref_info},ConstantFieldRefInfoParse{classIndex=9, nameAndTypeIndex=28, tag=9, name=CONSTANT_Fieldref_info},ConstantFieldRefInfoParse{classIndex=9, nameAndTypeIndex=29, tag=9, name=CONSTANT_Fieldref_info},ConstantStringInfoParse{index=30, tag=8, name=CONSTANT_String_info},ConstantMethodRefInfoParse{classIndex=31, nameAndTypeIndex=32, tag=10, name=CONSTANT_Methodref_info},ConstantFieldRefInfoParse{classIndex=33, nameAndTypeIndex=34, tag=9, name=CONSTANT_Fieldref_info},ConstantStringInfoParse{index=35, tag=8, name=CONSTANT_String_info},ConstantMethodRefInfoParse{classIndex=36, nameAndTypeIndex=37, tag=10, name=CONSTANT_Methodref_info},ConstantClassInfoParse{index=38, tag=7, name=CONSTANT_Class_info},ConstantClassInfoParse{index=39, tag=7, name=CONSTANT_Class_info},ConstantUtf8InfoParse{length=4, value='name', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=18, value='Ljava/lang/String;', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=3, value='age', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=1, value='I', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=6, value='<init>', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=22, value='(Ljava/lang/String;I)V', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=4, value='Code', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=15, value='LineNumberTable', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=18, value='LocalVariableTable', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=4, value='this', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=20, value='Lorg/example/Person;', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=4, value='play', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=21, value='(Ljava/lang/String;)V', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=13, value='StackMapTable', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=10, value='SourceFile', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=11, value='Person.java', tag=1, name=CONSTANT_Utf8_info},ConstantNameAndTypeInfoParse{nameIndex=15, signatureIndex=40, tag=12, name=CONSTANT_NameAndType_info},ConstantNameAndTypeInfoParse{nameIndex=11, signatureIndex=12, tag=12, name=CONSTANT_NameAndType_info},ConstantNameAndTypeInfoParse{nameIndex=13, signatureIndex=14, tag=12, name=CONSTANT_NameAndType_info},ConstantUtf8InfoParse{length=6, value='basket', tag=1, name=CONSTANT_Utf8_info},ConstantClassInfoParse{index=41, tag=7, name=CONSTANT_Class_info},ConstantNameAndTypeInfoParse{nameIndex=42, signatureIndex=43, tag=12, name=CONSTANT_NameAndType_info},ConstantClassInfoParse{index=44, tag=7, name=CONSTANT_Class_info},ConstantNameAndTypeInfoParse{nameIndex=45, signatureIndex=46, tag=12, name=CONSTANT_NameAndType_info},ConstantUtf8InfoParse{length=6, value='篮球', tag=1, name=CONSTANT_Utf8_info},ConstantClassInfoParse{index=47, tag=7, name=CONSTANT_Class_info},ConstantNameAndTypeInfoParse{nameIndex=48, signatureIndex=23, tag=12, name=CONSTANT_NameAndType_info},ConstantUtf8InfoParse{length=18, value='org/example/Person', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=16, value='java/lang/Object', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=3, value='()V', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=16, value='java/lang/String', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=6, value='equals', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=21, value='(Ljava/lang/Object;)Z', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=16, value='java/lang/System', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=3, value='out', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=21, value='Ljava/io/PrintStream;', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=19, value='java/io/PrintStream', tag=1, name=CONSTANT_Utf8_info},ConstantUtf8InfoParse{length=7, value='println', tag=1, name=CONSTANT_Utf8_info},}
// 类的access flag
AccessFlagParse{value=33, accessFlags=ACC_PUBLIC,ACC_SUPER,}
// 类的索引和父类的索引
ClassExtParse{thisClassIndex=9, superClassIndex=10}
// 类继承的接口
InterfaceParse{interfacesCount=0, interfaceInfoParses=}
// 类中变量
FieldParse{fieldCount=2, fieldItemParses=FieldItemParse{accessFlag=AccessFlagParse{value=1, accessFlags=ACC_PUBLIC,}, nameIndex=11, descriptorIndex=12, attributeCount=0, attributeInfoPars=},FieldItemParse{accessFlag=AccessFlagParse{value=1, accessFlags=ACC_PUBLIC,}, nameIndex=13, descriptorIndex=14, attributeCount=0, attributeInfoPars=},}
// 类中方法
MethodParse{methodCount=2, methodItemParses=MethodItemParse{accessFlag=AccessFlagParse{value=1, accessFlags=ACC_PUBLIC,}, nameIndex=15, descriptorIndex=16, attributeCount=1, attributeInfoPars=[AttributeInfoParse{nameIndex=17, attributeLength=89, infos=Info{value=0},Info{value=2},Info{value=0},Info{value=3},Info{value=0},Info{value=0},Info{value=0},Info{value=15},Info{value=42},Info{value=183},Info{value=0},Info{value=1},Info{value=42},Info{value=43},Info{value=181},Info{value=0},Info{value=2},Info{value=42},Info{value=28},Info{value=181},Info{value=0},Info{value=3},Info{value=177},Info{value=0},Info{value=0},Info{value=0},Info{value=2},Info{value=0},Info{value=18},Info{value=0},Info{value=0},Info{value=0},Info{value=18},Info{value=0},Info{value=4},Info{value=0},Info{value=0},Info{value=0},Info{value=8},Info{value=0},Info{value=4},Info{value=0},Info{value=9},Info{value=0},Info{value=9},Info{value=0},Info{value=10},Info{value=0},Info{value=14},Info{value=0},Info{value=11},Info{value=0},Info{value=19},Info{value=0},Info{value=0},Info{value=0},Info{value=32},Info{value=0},Info{value=3},Info{value=0},Info{value=0},Info{value=0},Info{value=15},Info{value=0},Info{value=20},Info{value=0},Info{value=21},Info{value=0},Info{value=0},Info{value=0},Info{value=0},Info{value=0},Info{value=15},Info{value=0},Info{value=11},Info{value=0},Info{value=12},Info{value=0},Info{value=1},Info{value=0},Info{value=0},Info{value=0},Info{value=15},Info{value=0},Info{value=13},Info{value=0},Info{value=14},Info{value=0},Info{value=2},}]},MethodItemParse{accessFlag=AccessFlagParse{value=1, accessFlags=ACC_PUBLIC,}, nameIndex=22, descriptorIndex=23, attributeCount=1, attributeInfoPars=[AttributeInfoParse{nameIndex=17, attributeLength=87, infos=Info{value=0},Info{value=2},Info{value=0},Info{value=2},Info{value=0},Info{value=0},Info{value=0},Info{value=18},Info{value=43},Info{value=18},Info{value=4},Info{value=182},Info{value=0},Info{value=5},Info{value=153},Info{value=0},Info{value=11},Info{value=178},Info{value=0},Info{value=6},Info{value=18},Info{value=7},Info{value=182},Info{value=0},Info{value=8},Info{value=177},Info{value=0},Info{value=0},Info{value=0},Info{value=3},Info{value=0},Info{value=18},Info{value=0},Info{value=0},Info{value=0},Info{value=14},Info{value=0},Info{value=3},Info{value=0},Info{value=0},Info{value=0},Info{value=15},Info{value=0},Info{value=9},Info{value=0},Info{value=16},Info{value=0},Info{value=17},Info{value=0},Info{value=18},Info{value=0},Info{value=19},Info{value=0},Info{value=0},Info{value=0},Info{value=22},Info{value=0},Info{value=2},Info{value=0},Info{value=0},Info{value=0},Info{value=18},Info{value=0},Info{value=20},Info{value=0},Info{value=21},Info{value=0},Info{value=0},Info{value=0},Info{value=0},Info{value=0},Info{value=18},Info{value=0},Info{value=11},Info{value=0},Info{value=12},Info{value=0},Info{value=1},Info{value=0},Info{value=24},Info{value=0},Info{value=0},Info{value=0},Info{value=3},Info{value=0},Info{value=1},Info{value=17},}]},}
// 类的其他属性,比如SourceFile
AttributeParse{attributeCount=1, attributeInfoPars=AttributeInfoParse{nameIndex=25, attributeLength=2, infos=Info{value=0},Info{value=26},},}

ClassFormat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class ClassFormat {
private List<Parse> parses = new ArrayList<>();

public ClassFormat() {
parses.add(new MagicParse()); //magic解析器
parses.add(new VersionParse()); // 版本解析器
parses.add(new ConstantParse()); // 常量池解析器
parses.add(new AccessFlagParse()); // class access flag解析器
parses.add(new ClassExtParse()); // class info解析器
parses.add(new InterfaceParse()); // class的接口解析器
parses.add(new FieldParse()); // field变量解析器
parses.add(new MethodParse()); // method方法解析器
parses.add(new AttributeParse()); // 类的其他属性解析器
}


public void parse(byte[] bytes) {
int start = 0;
for (Parse pars : parses) {
start = pars.parse(start, bytes);
}
}
}

MagicParse

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class MagicParse implements Parse { //u4

public String magic;

@Override
public int parse(int start, byte[] bytes) {
int magicLength = 4; // magic 长度为u4
byte[] magicCode = new byte[magicLength];
System.arraycopy(bytes, start, magicCode, 0, magicLength);
StringBuilder stringBuilder = new StringBuilder();
for (byte b : magicCode) {
int value = Byte.toUnsignedInt(b);
stringBuilder.append(Integer.toHexString(value).toUpperCase());
}

if (!"CAFEBABE".equals(stringBuilder.toString())) {
throw new RuntimeException("class error");
}

magic = stringBuilder.toString();

return start + magicLength;
}

@Override
public String toString() {
return "MagicParse{" +
"magic='" + magic + '\'' +
'}';
}
}

VersionParse

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class VersionParse implements Parse {
public int minor; // u2
public int major; // u2

@Override
public int parse(int start, byte[] bytes) {
minor = Utils.getU2Int(start, bytes); // u2 minor
start += 2;
major = Utils.getU2Int(start, bytes); // u2 major
return start + 2;
}

@Override
public String toString() {
return "VersionParse{" +
"minor=" + minor +
", major=" + major +
'}';
}
}

getU2Int

1
2
3
4
5
6
7
public static int getU2Int(int start, byte[] bytes) {
byte[] versionCode = new byte[2];
System.arraycopy(bytes, start, versionCode, 0, 2);// 2个字节
int high = Byte.toUnsignedInt(versionCode[0]); // 第一个字节是高位,这里将byte转位无符号的int
int low = Byte.toUnsignedInt(versionCode[1]); // 第二个字节是低位,这里将byte转位无符号的int
return high << 8 | low; // 高位左移8位 | 低位就是int值
}

未解析部分:属性表

属性表

深入理解JAVA虚拟机 180页部分

Code

  • 源码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public class Person {
    public String name;
    public int age;

    public Person(String name, int age) {
    this.name = name;
    this.age = age;
    }

    public void play(String name) {
    if (name.equals("basket")) {
    System.out.println("篮球");
    }

    }
    }
  • javap

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    public org.example.Person(java.lang.String, int);
    descriptor: (Ljava/lang/String;I)V
    flags: ACC_PUBLIC
    Code:
    stack=2, locals=3, args_size=3
    0: aload_0
    1: invokespecial #1 // Method java/lang/Object."<init>":()V
    4: aload_0
    5: aload_1
    6: putfield #2 // Field name:Ljava/lang/String;
    9: aload_0
    10: iload_2
    11: putfield #3 // Field age:I
    14: return
    LineNumberTable:
    line 8: 0
    line 9: 4
    line 10: 9
    line 11: 14
    LocalVariableTable:
    Start Length Slot Name Signature
    0 15 0 this Lorg/example/Person;
    0 15 1 name Ljava/lang/String;
    0 15 2 age I

    public void play(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: ACC_PUBLIC
    Code:
    stack=2, locals=2, args_size=2
    0: aload_1
    1: ldc #4 // String basket
    3: invokevirtual #5 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
    6: ifeq 17
    9: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
    12: ldc #7 // String 篮球
    14: invokevirtual #8 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
    17: return
    LineNumberTable:
    line 15: 0
    line 16: 9
    line 18: 17
    LocalVariableTable:
    Start Length Slot Name Signature
    0 18 0 this Lorg/example/Person;
    0 18 1 name Ljava/lang/String;

  • 我们的实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    方法:<init>
    aload_0
    invokespecial java/lang/Object <init> ()V
    aload_0
    aload_1
    putfield org/example/Person name Ljava/lang/String;
    aload_0
    iload_2
    putfield org/example/Person age I
    return
    方法:play
    aload_1
    ldc basket
    invokevirtual java/lang/String equals (Ljava/lang/Object;)Z
    ifeq name
    getstatic java/lang/System out Ljava/io/PrintStream;
    ldc 篮球
    invokevirtual java/io/PrintStream println (Ljava/lang/String;)V
    return
  • 原理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    @Override
    public int parse(int start, byte[] bytes) {
    nameIndex = Utils.getU2Int(start, bytes);
    start += 2;
    attributeLength = Utils.getU4Int(start, bytes);
    start += 4;

    String utfConstant = String.valueOf(constantParse.getUtfConstant(nameIndex));

    switch (utfConstant.toLowerCase()) {
    case "code":
    attributeFormatParse = new CodeParse(attributeLength,constantParse);
    break;
    default:
    attributeFormatParse = new Info(attributeLength);
    break;
    }

    start = attributeFormatParse.parse(start, bytes);

    return start;
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    package org.example.bytecode.parse.attribute;

    import org.example.bytecode.Utils;
    import org.example.bytecode.parse.ConstantParse;
    import org.example.bytecode.parse.constant.ConstantInfoParse;

    public class CodeParse extends AttributeFormatParse {
    public int attributeNameIndex;
    public int attributeLength;
    public int maxStack;
    public int maxLocals;
    public int codeLength;

    public int exceptionTableLength;

    public int attributesCount;


    private ConstantParse constantParse;

    public CodeParse(int length, ConstantParse constantParse) {
    super(length);
    this.constantParse = constantParse;
    }

    @Override
    public int parse(int start, byte[] code) {
    int index = start;
    maxStack = Utils.getU2Int(index, code);//u2
    index += 2;
    maxLocals = Utils.getU2Int(index, code); //u2
    index += 2;
    codeLength = Utils.getU4Int(index, code); //u4
    index += 4;

    int l = index + codeLength;
    while (index < l) {
    int cmd = Utils.getU1Int(index, code);
    index += 1;
    String cmdStr = Utils.getCMD(cmd); // 这里是复制的asm中的字节码数组
    System.out.print(cmdStr);
    int paramsLength = Utils.getParamsLength(cmd); // 这里是复制的asm中的字节码后面参数的length数组
    if (paramsLength >= 0) {
    if (paramsLength == 1) {
    int u1Int = Utils.getU1Int(index, code);
    Object utfConstant = constantParse.getUtfConstant(u1Int);
    System.out.print(" " + String.valueOf(utfConstant));
    } else if (paramsLength == 2) {
    int u2Int = Utils.getU2Int(index, code);
    Object utfConstant = constantParse.getUtfConstant(u2Int);
    System.out.print(" " + String.valueOf(utfConstant));
    } else {
    for (int i = 0; i < paramsLength; i++) {
    System.out.print(" " + Utils.getU1Int(index + i, code));
    }
    }
    index += paramsLength;
    } else {
    break;
    }
    System.out.print("\n");
    }
    index += codeLength;

    // 这里是 exception和attribute,attribute主要解析LineNumberTable和LocalVariableTable即可,后续实现
    // exceptionTableLength = Utils.getU2Int(index, code);
    // index += 2;
    // // todo exception info
    // attributeLength = Utils.getU2Int(index, code);
    // index += 2;
    // // todo attribute


    return start + length;
    }
    }

Why

最近读了深入理解java虚拟机,为了加深对于字节码的理解和记忆,写了一个class解析器

What1-Class结构

字节码

image.png

Class结构

class_2.png

class解析器

系统架构图 (1).png

Constant Pool

  • CONSTANT_Utf8_info (tag/length/bytes-u1)
  • CONSTANT_Integer_info (tag/bytes-u4)
  • CONSTANT_Float_info (tag/bytes-u4)
  • CONSTANT_Long_info (tag/bytes-u8)
  • CONSTANT_Double_info (tag/bytes-u8)
  • CONSTANT_Class_info (tag/index)
  • CONSTANT_String_info (tag/index)
  • CONSTANT_Fieldref_info (tag/index类/index)
  • CONSTANT_Methodref_info (tag/index类/index)
  • CONSTANT_Interface-Methodref_info (tag/index接口类/index)
  • CONSTANT_NameAndType_info (tag/index名称/index签名)
  • CONSTANT_Method-Handle_info
  • CONSTANT_Method-type_info
  • CONSTANT_Invoke-Dynamic_info

attribute

  • Code 方法表
  • LineNumberTable 调试表
  • LocalVariableTable 本地变量表
  • SourceFile 源文件表
  • Exceptions 异常表
  • ConstantValue 常量表
  • InnerClasses 内部类表
  • Deprecated 废弃标识
  • Synthetic 表示方法或者字段
  • StackMapTable 类型检查器
  • Signature 泛型的方法签名 - 泛型会类型擦除
  • BootstrapMethods invokedymic相关
  • LocalVariableTypeTable 泛型相关
  • 还有其他一些没有实现

解析器设计

1
2
3
public interface Parse {
int parse(int start, byte[] code);
}

start:开始解析位置
code:字节码
return:结束位置

1
2
3
4
5
6
7
8
public class Bytes {
public byte[] bytes;
public int start;
public int readByte() {}
public int readShort() {}
public int readInt() {}
...
}

What2-字节码指令

code属性表

未命名文件.png

  • 字节码指令是在Method表的 Code Attribute表中。
  • class字节码指令的执行是基于栈的
  • 字节码指令是用u1来表示的,也就限制了字节码指令种类不能超过255个;实际字节码的种类数量为201种

字节码指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Person {
public static final String A = "final_static_a";
public static String B = "only_static_b";
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public int method1(int a, int b) {
int d = 100;
int c = a + b;
d += c;
return d * c;
}
public int method2(String name) {
if (this.name.equals(name)) {
return 1;
}
return 0;
}
}

clinit

1
2
public static final String A = "final_static_a";
public static String B = "only_static_b";
1
2
3
4
5
static void <clinit>() {
ldc "only_static_b" //入栈读取值
putstatic 'org/example/Person.B','Ljava/lang/String;' //出栈ldc指令和赋值变量B
return
}

init

1
2
3
4
5
6
7
public String name;
public int age;

public Person(String name, int age) {
this.name = name;
this.age = age;
}
1
2
3
4
5
6
7
8
9
10
11
public void <init>(String a,int b) {
aload 0 // this入栈
invokespecial 'java/lang/Object.<init>','()V' //this出栈,执行Object构造
aload 0 // this入栈
aload 1 // a入栈
putfield 'org/example/Person.name','Ljava/lang/String;' //出栈2个将a的值赋值给this.name
aload 0 // this入栈
iload 2 // b入栈
putfield 'org/example/Person.age','I' // 出栈2个,赋值给this.age
return
}

method1

1
2
3
4
5
6
7
public int method1(int a, int b) {
int d = 100;
int c = a + b;
d += c;
d += 100;
return d * c;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public int method1(int a,int b) {
bipush 100 //100入栈
istore 3 // 出栈存到3号槽中
iload 1 // 读取1号槽a
iload 2 // 读取2号槽b
iadd // 前面两个出栈,相加值入栈
istore 4 // 出栈将新的值存到4号槽
iload 3 // 读取3号槽
iload 4 // 读取4号槽
iadd // 前两个出栈,相加值入栈
istore 3 // 出栈存到3号槽
iinc 3,100 // 将3号槽的值加100
iload 3 // 入栈3号槽
iload 4 // 入栈4号槽
imul // 前两个出栈相乘的值入栈
ireturn
}

method2

1
2
3
4
5
6
public int method2(String name) {
if (this.name.equals(name)) {
return 1;
}
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
public int method2(String a) {
aload 0 // 读取0号槽 this
getfield 'org/example/Person.name','Ljava/lang/String;' //出栈this,入栈name值
aload 1 // 入栈1号槽 a值
invokevirtual 'java/lang/String.equals','(Ljava/lang/Object;)Z' //出栈上面2个值,执行equals结果入栈
ifeq l0 // 出栈结果等于0,如果等于跳转到l0
iconst_1 // 1入栈
ireturn // 出栈返回
l0
iconst_0 // 0入栈
ireturn // 出栈返回
}

tableswitch和lookupswitch