- java封装的太好了,导致我们只能看到表面的东西,要想更深层次了解原理有一个东西要用到就是javap 反编译.class文件,看到指令集
下面结合synchronized 关键字底层原理熟悉 javap用法
- 第一创建一个类
public class test {
public synchronized void test1(){
}
public void test2(){
synchronized(this) {
int i = 0;
i++;
}
}
public void test3(){
synchronized(test.class) {
int i = 0;
i++;
}
}
}
然后用javac命令编译
javac test.java 生成test.class
然后用javap -v test.class 反编译出如下结果
Last modified 2022-2-28; size 546 bytes
MD5 checksum 3a0c6ab13146d967a1782810ffe7e796
Compiled from "test.java"
public class com.test.eventtest.test
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #3.#17 // java/lang/Object."<init>":()V
#2 = Class #18 // com/test/eventtest/test
#3 = Class #19 // java/lang/Object
#4 = Utf8 <init>
#5 = Utf8 ()V
#6 = Utf8 Code
#7 = Utf8 LineNumberTable
#8 = Utf8 test1
#9 = Utf8 test2
#10 = Utf8 StackMapTable
#11 = Class #18 // com/test/eventtest/test
#12 = Class #19 // java/lang/Object
#13 = Class #20 // java/lang/Throwable
#14 = Utf8 test3
#15 = Utf8 SourceFile
#16 = Utf8 test.java
#17 = NameAndType #4:#5 // "<init>":()V
#18 = Utf8 com/test/eventtest/test
#19 = Utf8 java/lang/Object
#20 = Utf8 java/lang/Throwable
{
public com.test.eventtest.test();
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
public synchronized void test1();
descriptor: ()V
flags: ACC_PUBLIC, ACC_SYNCHRONIZED
Code:
stack=0, locals=1, args_size=1
0: return
LineNumberTable:
line 6: 0
public void test2();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=4, args_size=1
0: aload_0
1: dup
2: astore_1
3: monitorenter
4: iconst_0
5: istore_2
6: iinc 2, 1
9: aload_1
10: monitorexit
11: goto 19
14: astore_3
15: aload_1
16: monitorexit
17: aload_3
18: athrow
19: return
Exception table:
from to target type
4 11 14 any
14 17 14 any
LineNumberTable:
line 9: 0
line 10: 4
line 11: 6
line 12: 9
line 13: 19
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 14
locals = [ class com/test/eventtest/test, class java/lang/Object ]
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 4
public void test3();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=4, args_size=1
0: ldc #2 // class com/test/eventtest/test
2: dup
3: astore_1
4: monitorenter
5: iconst_0
6: istore_2
7: iinc 2, 1
10: aload_1
11: monitorexit
12: goto 20
15: astore_3
16: aload_1
17: monitorexit
18: aload_3
19: athrow
20: return
Exception table:
from to target type
5 12 15 any
15 18 15 any
LineNumberTable:
line 16: 0
line 17: 5
line 18: 7
line 19: 10
line 20: 20
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 15
locals = [ class com/test/eventtest/test, class java/lang/Object ]
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 4
}
SourceFile: "test.java"
可以看出加在方法上 编译会添加 flags: ACC_SYNCHRONIZED
添加到代码块上,编译会添加指令 monitorenter monitorexit ,这里实则就是用到了引用计数, monitor为0 的时候可以进入,当别的线程 monitorenter 引用计数+1,此线程只能等待。从而实现线程同步。
© 版权声明
文章版权归作者所有,未经允许请勿转载。如内容涉嫌侵权,请在本页底部进入<联系我们>进行举报投诉!
THE END
















暂无评论内容