public class MovingAverage {
private int count = 0;
private double sum = 0.0D;
public void submit(double value) {
this.count++;
this.sum += value;
}
public double getAvg() {
if (0 == this.count) {
return sum;
}
return this.sum / this.count;
}
}
public class ForLoopTest {
private static int[] numbers = {1, 6, 8};
public static void main(String[] args) {
MovingAverage ma = new MovingAverage();
for (int number : numbers) {
ma.submit(number);
}
double avg = ma.getAvg();
}
}
编译java文件为class
javac -g *.java
反编译ForLoopTest
javap -c -v ForLoopTest
Classfile /F:/lwy/workspace/ByteCode/src/demo/ForLoopTest.class
Last modified 2021-1-6; size 772 bytes
MD5 checksum 6fbe54272614cdc3ecee24916f0c9cba
Compiled from "ForLoopTest.java"
public class demo.ForLoopTest
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #8.#35 // java/lang/Object."<init>":()V
#2 = Class #36 // demo/MovingAverage
#3 = Methodref #2.#35 // demo/MovingAverage."<init>":()V
#4 = Fieldref #7.#37 // demo/ForLoopTest.numbers:[I
#5 = Methodref #2.#38 // demo/MovingAverage.submit:(D)V
#6 = Methodref #2.#39 // demo/MovingAverage.getAvg:()D
#7 = Class #40 // demo/ForLoopTest
#8 = Class #41 // java/lang/Object
#9 = Utf8 numbers
#10 = Utf8 [I
#11 = Utf8 <init>
#12 = Utf8 ()V
#13 = Utf8 Code
#14 = Utf8 LineNumberTable
#15 = Utf8 LocalVariableTable
#16 = Utf8 this
#17 = Utf8 Ldemo/ForLoopTest;
#18 = Utf8 main
#19 = Utf8 ([Ljava/lang/String;)V
#20 = Utf8 number
#21 = Utf8 I
#22 = Utf8 args
#23 = Utf8 [Ljava/lang/String;
#24 = Utf8 ma
#25 = Utf8 Ldemo/MovingAverage;
#26 = Utf8 avg
#27 = Utf8 D
#28 = Utf8 StackMapTable
#29 = Class #23 // "[Ljava/lang/String;"
#30 = Class #36 // demo/MovingAverage
#31 = Class #10 // "[I"
#32 = Utf8 <clinit>
#33 = Utf8 SourceFile
#34 = Utf8 ForLoopTest.java
#35 = NameAndType #11:#12 // "<init>":()V
#36 = Utf8 demo/MovingAverage
#37 = NameAndType #9:#10 // numbers:[I
#38 = NameAndType #42:#43 // submit:(D)V
#39 = NameAndType #44:#45 // getAvg:()D
#40 = Utf8 demo/ForLoopTest
#41 = Utf8 java/lang/Object
#42 = Utf8 submit
#43 = Utf8 (D)V
#44 = Utf8 getAvg
#45 = Utf8 ()D
{
public demo.ForLoopTest();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>
":()V
4: return
LineNumberTable:
line 3: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Ldemo/ForLoopTest;
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=6, args_size=1
0: new #2 // class demo/MovingAverage
3: dup
4: invokespecial #3 // Method demo/MovingAverage."<ini
t>":()V
7: astore_1
8: getstatic #4 // Field numbers:[I
11: astore_2
12: aload_2
13: arraylength
14: istore_3
15: iconst_0
16: istore 4
18: iload 4
20: iload_3
21: if_icmpge 43
24: aload_2
25: iload 4
27: iaload
28: istore 5
30: aload_1
31: iload 5
33: i2d
34: invokevirtual #5 // Method demo/MovingAverage.submi
t:(D)V
37: iinc 4, 1
40: goto 18
43: aload_1
44: invokevirtual #6 // Method demo/MovingAverage.getAv
g:()D
47: dstore_2
48: return
LineNumberTable:
line 8: 0
line 9: 8
line 10: 30
line 9: 37
line 12: 43
line 13: 48
LocalVariableTable:
Start Length Slot Name Signature
30 7 5 number I
0 49 0 args [Ljava/lang/String;
8 41 1 ma Ldemo/MovingAverage;
48 1 2 avg D
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 18
locals = [ class "[Ljava/lang/String;", class demo/MovingAverage, clas
s "[I", int, int ]
stack = []
frame_type = 248 /* chop */
offset_delta = 24
static {};
descriptor: ()V
flags: ACC_STATIC
Code:
stack=4, locals=0, args_size=0
0: iconst_3
1: newarray int
3: dup
4: iconst_0
5: iconst_1
6: iastore
7: dup
8: iconst_1
9: bipush 6
11: iastore
12: dup
13: iconst_2
14: bipush 8
16: iastore
17: putstatic #4 // Field numbers:[I
20: return
LineNumberTable:
line 5: 0
}
SourceFile: "ForLoopTest.java"
反编译解读:MovingAverage ma = new MovingAverage();
new #2为创建MoveingAverage对象
dup则复制操作数栈顶的值
invokespecial #3则为执行#3所对应的函数为MoveingAverage的init构造函数
astore_1则表示将栈顶元素的引用赋值给LocalVariableTable中slot是1变量ma
getstatic #4则表示获取指定类的静态域,并将其值压入栈顶---实则是number的引用
astore_2则将栈顶引用型数值存入第2个本地变量
aload_2则表示将第2个引用类型本地变量推送至栈顶
arraylength获得数组的长度值并压入栈顶
istore_3将栈顶int型数值存入第3个本地变量
iconst_0将int型0推送至栈顶
istore 4将栈顶int型数值存入指定本地变量
iload 4将指定的int型本地变量推送至栈顶(18行)
iload_3将第3个int型本地变量推送至栈顶
if_icmpge 43比较栈顶两int型数值大小,当结果大于等于0时跳转到多少行
aload_2将第2个引用类型本地变量推送至栈顶
iload 4将指定的int型本地变量推送至栈顶
iaload将int型数组指定索引的值推送至栈顶(将索引4中值所对应的值压到栈顶)
istore 5将栈顶int型数值存入指定本地变量(把【1,6,8】6赋值给第5个本地变量)
aload_1将第1个引用类型本地变量推送至栈顶(把ma压栈)
iload 5将指定的int型本地变量推送至栈顶(把6压栈)
i2d将栈顶int型数值强制转换成double型数值并将结果压入栈顶(把6出栈,后转换成double后压栈)
invokevirtual #5调用实例方法(执行ma.submit(6)方法)
iinc 4,1将指定int型变量增加指定值,可以有两个变量,分别表示index, const,index指第index个int型本地变量,const增加的值(第4个本地变量的值+1,也就是索引值+1)
goto 18无条件跳转18行
以上利用本地的第二个、第三个、第四个变量进行记录数组、数组长度、及当前索引值
aload_1把ma压栈
invokevirtual #6执行ma.getAvg()函数返回值在栈顶
dstore_2将栈顶double型数值存入第2个本地变量avg
return函数结束