代码如下
public class Exercise {
static void print(Exercise e1,Exercise e2) {
System.out.println(e1==(e1=e2));
}
public static void main(String[] args) {
Exercise e1 = new Exercise();
Exercise e2 = new Exercise();
print(e1,e2);
}
}
编译后,使用javap 查看字节码
javap -verbose Exercise.class
参考指令:https://cs.au.dk/~mis/dOvs/jvmspec/ref-Java.html
可以看出, 5行的时候,将第二个局部变量压入两次。
6行的时候,弹出栈顶局部变量。 导致之后比较的时候,栈顶的两个引用不相同。 因此输出false.
相关指令
- 0x59 dup 复制栈顶数值并将复制值压入栈顶
- 0x19 aload 将指定的引用类型本地变量推送至栈顶
- 0x3a astore 将栈顶引用类型数值存入指定本地变量
- 0xa0 if_icmpne 比较栈顶两int型数值大小, 当结果不等于0时跳转
- 0xb6 invokevirtual 调用实例方法
相关字节码
D:\temp\test>javap -verbose Exercise.class
Classfile /D:/temp/test/Exercise.class
Last modified 2019-2-12; size 569 bytes
MD5 checksum ca83d3f8fc84d49a8e6cec7faeb7b527
Compiled from "Exercise.java"
public class Exercise
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #7.#21 // java/lang/Object."<init>":()V
#2 = Fieldref #22.#23 // java/lang/System.out:Ljava/io/PrintStream;
#3 = Methodref #24.#25 // java/io/PrintStream.println:(Z)V
#4 = Class #26 // Exercise
#5 = Methodref #4.#21 // Exercise."<init>":()V
#6 = Methodref #4.#27 // Exercise.print:(LExercise;LExercise;)V
#7 = Class #28 // java/lang/Object
#8 = Utf8 <init>
#9 = Utf8 ()V
#10 = Utf8 Code
#11 = Utf8 LineNumberTable
#12 = Utf8 print
#13 = Utf8 (LExercise;LExercise;)V
#14 = Utf8 StackMapTable
#15 = Class #29 // java/io/PrintStream
#16 = Class #26 // Exercise
#17 = Utf8 main
#18 = Utf8 ([Ljava/lang/String;)V
#19 = Utf8 SourceFile
#20 = Utf8 Exercise.java
#21 = NameAndType #8:#9 // "<init>":()V
#22 = Class #30 // java/lang/System
#23 = NameAndType #31:#32 // out:Ljava/io/PrintStream;
#24 = Class #29 // java/io/PrintStream
#25 = NameAndType #33:#34 // println:(Z)V
#26 = Utf8 Exercise
#27 = NameAndType #12:#13 // print:(LExercise;LExercise;)V
#28 = Utf8 java/lang/Object
#29 = Utf8 java/io/PrintStream
#30 = Utf8 java/lang/System
#31 = Utf8 out
#32 = Utf8 Ljava/io/PrintStream;
#33 = Utf8 println
#34 = Utf8 (Z)V
{
public Exercise();
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
static void print(Exercise, Exercise);
descriptor: (LExercise;LExercise;)V
flags: ACC_STATIC
Code:
stack=4, locals=2, args_size=2
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStrea
3: aload_0
4: aload_1
5: dup
6: astore_0
7: if_acmpne 14
10: iconst_1
11: goto 15
14: iconst_0
15: invokevirtual #3 // Method java/io/PrintStream.println:(Z)V
18: return
LineNumberTable:
line 6: 0
line 7: 18
StackMapTable: number_of_entries = 2
frame_type = 78 /* same_locals_1_stack_item */
stack = [ class java/io/PrintStream ]
frame_type = 255 /* full_frame */
offset_delta = 0
locals = [ class Exercise, class Exercise ]
stack = [ class java/io/PrintStream, int ]
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=3, args_size=1
0: new #4 // class Exercise
3: dup
4: invokespecial #5 // Method "<init>":()V
7: astore_1
8: new #4 // class Exercise
11: dup
12: invokespecial #5 // Method "<init>":()V
15: astore_2
16: aload_1
17: aload_2
18: invokestatic #6 // Method print:(LExercise;LExercise;)V
21: return
LineNumberTable:
line 10: 0
line 11: 8
line 12: 16
line 13: 21
}
SourceFile: "Exercise.java"
PS:个人理解,欢迎指正。