3

JVM如何执行synchronized修饰的方法

 2 years ago
source link: https://www.heapdump.cn/article/3236437
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
JVM如何执行synchronized修饰的方法 | HeapDump性能社区

JVM如何执行synchronized修饰的方法原创

JVM如何执行synchronized修饰的方法

哈喽,小伙伴们好,我就是Java圈最卷的硬核男人子牙。手撸过JVM、JMM、synchronized、线程池、NIO…

近期准备写一个专栏:从Hotspot源码角度剖析synchronized。前前后后大概有10篇,会全网发,写完后整理成电子书放公众号供大家下载。对本专栏感兴趣的、希望彻彻底底学明白synchronized的小伙伴可以关注一波。电子书整理好了会通过公众号群发告知大家。我的公众号:硬核子牙。

市面上关于synchronized的资料已经很多了,我这个专栏跟那些资料有啥差别呢:

  1. 更系统。市面上目前虽然资料众多,但都是零散的。有些资料讲得东西甚至是相互冲突的,都不知道信谁的。我准备从Java层面到JVM层面到操作系统层面系统的去分析用synchronized后呈现的每个现象背后的本质。synchronized很多知识点市面上是没有资料讲的,我给它补上。

  2. 更接近真相。市面上的很多资料,有的是基于字节码解释器那块的代码yy出来的,有的是东拼西凑整合出来的,各个说的都像真的一样,把看的人搞蒙圈了。我准备从模板解释器代码入手,单步调试着研究,有些不确定的自己写代码去证明,争取分享给大家的都是本来如此的知识。不确定的地方我会标注出来。

  1. 授人以鱼不如授人以渔。我会以大家学完后能够手写出synchronized的标准来设计这个专栏。因为从我自己研究的角度来说,抛开语言的障碍,synchronized的每种机制如果让你实现你手足无措,那你还是没有真正地理解synchronized。言外之意就是你不一定要去手写,但是你在脑海中回想,比如CAS、锁膨胀、锁对象加锁解锁……你大概知道代码是怎么写的。

本篇文章是第一篇,聚焦分析JVM是如何执行synchronized修饰的方法的:

  1. 编译系统是如何处理synchronized关键字的

  2. JVM是如何选出锁定的对象的

  3. 模板解释器为了提升效率做了什么

  4. 什么情况会由执行例程切入C++代码

  5. 如何单步调试synchronized

01

方法入口点

JVM执行Java方法都需要先构建运行环境,再去执行字节码指令。

这个运行环境包括:创建栈帧、从调用者堆栈拷贝参数、给this指针赋值…如果是synchronized修饰的方法,还需要:根据是否是静态方法来计算出锁对象,即是当前对象实例还是Class对象、进行上锁…

640?wx_fmt=png

因为调用每个方法都需要构建运行环境,都需要做这些事情,所以JVM把这套流程打包,封装成一个一个的执行流程。在JVM术语中,一般字节码指令的处理逻辑称为执行例程,这里为了做区分,起了个新的名字,叫entry point,翻译过来就是入口点。

JVM中有很多entry point,都存储在entry table中。与方法调用相关的比较常见的是这四个。非native方法一般对应的就是前两个入口点,被synchronized修饰对应的是zerolocals_synchronized,否则是zerolocals。

640?wx_fmt=png

这些entry point是什么时候生成的呢?JVM启动的时候,看代码

640?wx_fmt=png

那Java中的每个方法,何时与这些入口点进行绑定的呢?在链接阶段。看代码

640?wx_fmt=png

好像没看到synchronized修饰的方法的入口点是如何绑定的对吧。这个得追entry_for_method代码逻辑

640?wx_fmt=png

02

JVM是如何执行synchronized修饰的方法的呢?这个得从编译阶段、链接阶段、运行阶段三个阶段来分析。任何语言的任何语法糖都是由编译系统与运行系统配合完成的。这三个阶段中,编译阶段是编译系统做的事情,链接阶段与运行阶段是运行系统做的事情。接下来展开来说下。

编译系统

JVM在运行时是如何知道我现在要执行的方法有没有被synchronized修饰呢?是通过方法的访问权限为来识别的。

640?wx_fmt=png

这个数据是在编译阶段生成的,通过IDEA插件jclasslib可查看。

运行系统

如果是synchronized代码块,那在链接阶段会把这个方法当成普通的方法来处理,绑定的执行流就是zerolocals,最终处理synchronized逻辑是在执行monitorenter指令时。

如果是synchronized修饰方法,在链接阶段绑定执行流zerolocals_synchronized。这两者的区别是什么呢?其实生成的执行流是同一套代码,区别就是有个判断,如果是synchronized修饰的方法,会执行lock_method。看代码。

640?wx_fmt=png

lock_method方法的逻辑是汇编风格写出来的,不太好理解,我就用伪代码解释下

640?wx_fmt=png

至此,JVM是如何执行synchronized修饰的方法的逻辑就讲完了。当然,synchronized还有很多很多内容,我会逐步分享给大家。感兴趣的小伙伴可以关注一波。我的公众号:硬核子牙。

03

推荐阅读

1、技术人如何才能拿到百万年薪?

2、为什么他们成为了技术大牛?

3、深入剖析Lambda表达式的底层实现原理

640?wx_fmt=png

你好,我是子牙。十余年技术生涯,一路披荆斩棘从小白到技术总监到大厂中间件到创业。技术栈如汇编、C语言、C++、Windows内核、Linux内核及特别喜欢研究虚拟机底层实现,对JVM有深入研究。分享的文章偏硬核,很硬的那种。不考虑交个朋友吗?关注硬核子牙:

3213941


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK