字节码分析-控制流
源码
package java.bytecode;
/**
* 控制流示例 - 演示if-else、switch、for循环、while循环、增强for循环
*/
public class ControlFlowExample {
// if-else示例
public void ifElseExample(int value) {
if (value > 0) {
System.out.println("Positive");
} else if (value < 0) {
System.out.println("Negative");
} else {
System.out.println("Zero");
}
}
// switch示例
public void switchExample(int value) {
switch (value) {
case 1:
System.out.println("One");
break;
case 2:
System.out.println("Two");
break;
default:
System.out.println("Other");
}
}
// for循环示例
public void forLoopExample() {
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
}
// 增强for循环示例
public void enhancedForLoopExample(String[] array) {
for (String item : array) {
System.out.println(item);
}
}
// while循环示例
public void whileLoopExample() {
int i = 0;
while (i < 10) {
System.out.println(i);
i++;
}
}
}
结构化反解析
Classfile /D:/zcp/github/yggdrasil/java/bytecode/ControlFlowExample.class
Last modified 2025-12-3; size 1119 bytes
MD5 checksum 838814412d6efb6ccb3fbd152537cd4e
Compiled from "ControlFlowExample.java"
public class java.bytecode.ControlFlowExample
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #2.#3 // java/lang/Object."<init>":()V
#2 = Class #4 // java/lang/Object
#3 = NameAndType #5.#6 // "<init>":()V
#4 = Utf8 java/lang/Object
#5 = Utf8 <init>
#6 = Utf8 ()V
#7 = Fieldref #8.#9 // java/lang/System.out:Ljava/io/PrintStream;
#8 = Class #10 // java/lang/System
#9 = NameAndType #11:#12 // out:Ljava/io/PrintStream;
#10 = Utf8 java/lang/System
#11 = Utf8 out
#12 = Utf8 Ljava/io/PrintStream;
#13 = String #14 // Positive
#14 = Utf8 Positive
#15 = Methodref #16.#17 // java/io/PrintStream.println:(Ljava/lang/String;)V
#16 = Class #18 // java/io/PrintStream
#17 = NameAndType #19:#20 // println:(Ljava/lang/String;)V
#18 = Utf8 java/io/PrintStream
#19 = Utf8 println
#20 = Utf8 (Ljava/lang/String;)V
#21 = String #22 // Negative
#22 = Utf8 Negative
#23 = String #24 // Zero
#24 = Utf8 Zero
#25 = String #26 // One
#26 = Utf8 One
#27 = String #28 // Two
#28 = Utf8 Two
#29 = String #30 // Other
#30 = Utf8 Other
#31 = Methodref #16.#32 // java/io/PrintStream.println:(I)V
#32 = NameAndType #19:#33 // println:(I)V
#33 = Utf8 (I)V
#34 = Class #35 // java/bytecode/ControlFlowExample
#35 = Utf8 java/bytecode/ControlFlowExample
#36 = Utf8 Code
#37 = Utf8 LineNumberTable
#38 = Utf8 ifElseExample
#39 = Utf8 StackMapTable
#40 = Utf8 switchExample
#41 = Utf8 forLoopExample
#42 = Utf8 enhancedForLoopExample
#43 = Utf8 ([Ljava/lang/String;)V
#44 = Class #45 // "[Ljava/lang/String;"
#45 = Utf8 [Ljava/lang/String;
#46 = Utf8 whileLoopExample
#47 = Utf8 SourceFile
#48 = Utf8 ControlFlowExample.java
{
public void ifElseExample(int);
descriptor: (I)V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: iload_1
1: ifle 15
4: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
7: ldc #13 // String Positive
9: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
12: goto 38
15: iload_1
16: ifge 30
19: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
22: ldc #21 // String Negative
24: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
27: goto 38
30: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
33: ldc #23 // String Zero
35: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
38: return
LineNumberTable:
line 10: 0
line 11: 4
line 12: 15
line 13: 19
line 15: 30
line 17: 38
public void switchExample(int);
descriptor: (I)V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: iload_1
1: lookupswitch { // 2
1: 28
2: 39
default: 50
}
28: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
31: ldc #25 // String One
33: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
36: goto 58
39: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
42: ldc #27 // String Two
44: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
47: goto 58
50: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
53: ldc #29 // String Other
55: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
58: return
LineNumberTable:
line 21: 0
line 23: 28
line 24: 36
line 26: 39
line 27: 47
line 29: 50
line 31: 58
public void forLoopExample();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=1
0: iconst_0
1: istore_1
2: iload_1
3: bipush 10
5: if_icmpge 21
8: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
11: iload_1
12: invokevirtual #31 // Method java/io/PrintStream.println:(I)V
15: iinc 1, 1
18: goto 2
21: return
LineNumberTable:
line 35: 0
line 36: 8
line 35: 15
line 38: 21
public void enhancedForLoopExample(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC
Code:
stack=2, locals=6, args_size=2
0: aload_1
1: astore_2
2: aload_2
3: arraylength
4: istore_3
5: iconst_0
6: istore 4
8: iload 4
10: iload_3
11: if_icmpge 34
14: aload_2
15: iload 4
17: aaload
18: astore 5
20: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
23: aload 5
25: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
28: iinc 4, 1
31: goto 8
34: return
LineNumberTable:
line 42: 0
line 43: 20
line 42: 28
line 45: 34
public void whileLoopExample();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=1
0: iconst_0
1: istore_1
2: iload_1
3: bipush 10
5: if_icmpge 21
8: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
11: iload_1
12: invokevirtual #31 // Method java/io/PrintStream.println:(I)V
15: iinc 1, 1
18: goto 2
21: return
LineNumberTable:
line 49: 0
line 50: 2
line 51: 8
line 52: 15
line 54: 21
}
SourceFile: "ControlFlowExample.java"
详细说明
条件跳转指令
ifle- 如果栈顶int值小于等于0,则跳转ifge- 如果栈顶int值大于等于0,则跳转if_icmpge- 比较两个int值,如果第一个大于等于第二个,则跳转goto- 无条件跳转
if-else结构
if-else语句被转换为条件跳转指令:
if (value > 0) {
// 正数处理
} else if (value < 0) {
// 负数处理
} else {
// 零处理
}
字节码实现:
0: iload_1 // 加载value到栈
1: ifle 15 // 如果<=0,跳转到15
4: ... // 正数处理
12: goto 38 // 跳转到结束
15: iload_1 // 重新加载value
16: ifge 30 // 如果>=0,跳转到30
19: ... // 负数处理
27: goto 38 // 跳转到结束
30: ... // 零处理
38: return
switch语句
switch语句使用lookupswitch或tableswitch指令:
1: lookupswitch { // 2
1: 28
2: 39
default: 50
}
lookupswitch- 用于稀疏的case值(case值不连续)tableswitch- 用于密集的case值(case值连续)
for循环
for循环被转换为条件跳转结构:
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
字节码实现:
0: iconst_0 // 初始化i=0
1: istore_1 // 存储i
2: iload_1 // 加载i
3: bipush 10 // 加载10
5: if_icmpge 21 // 如果i>=10,跳转到21(结束)
8: ... // 循环体
15: iinc 1, 1 // i++
18: goto 2 // 跳转到条件判断
21: return
增强for循环
增强for循环被转换为传统的索引循环:
for (String item : array) {
System.out.println(item);
}
字节码实现:
0: aload_1 // 加载数组
1: astore_2 // 存储到局部变量2
2: aload_2 // 加载数组
3: arraylength // 获取数组长度
4: istore_3 // 存储长度
5: iconst_0 // 初始化索引i=0
6: istore 4 // 存储索引
8: iload 4 // 加载索引
10: iload_3 // 加载长度
11: if_icmpge 34 // 如果i>=length,跳转到34
14: aload_2 // 加载数组
15: iload 4 // 加载索引
17: aaload // 获取array[i]
18: astore 5 // 存储到item
20: ... // 循环体
28: iinc 4, 1 // i++
31: goto 8 // 跳转到条件判断
34: return
while循环
while循环与for循环的字节码结构类似,都是条件跳转:
while (i < 10) {
System.out.println(i);
i++;
}
字节码实现与for循环基本相同,只是初始化部分在循环外部。