性能文章>死磕synchronized一:JVM如何执行synchronized修饰的方法>

死磕synchronized一:JVM如何执行synchronized修饰的方法原创

2175018

哈喽,小伙伴们好,我就是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对象、进行上锁…

 

 

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

 

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

 

 

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

 

 

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

 

 

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

 

02

如何执行

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

 

编译系统

 

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

 

 

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

 

运行系统

 

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

 

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

 

 

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

 

 

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

03

推荐阅读

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

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

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

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

点赞收藏
分类:标签:
子牙_公号硬核子牙

对编程语言的设计与实现有浓厚兴趣。聚焦Hotspot源码、Linux内核研究,硬核干货分享

请先登录,感受更多精彩内容
快去登录吧,你将获得
  • 浏览更多精彩评论
  • 和开发者讨论交流,共同进步

为你推荐

怒啃 24 小时,终于搞懂上下文切换!

怒啃 24 小时,终于搞懂上下文切换!

【译】一次Docker 中的 Java 内存消耗问题的排查之旅

【译】一次Docker 中的 Java 内存消耗问题的排查之旅

JVM 常见线上问题:CPU100%、内存泄露的问题排查

JVM 常见线上问题:CPU100%、内存泄露的问题排查

FullGC没及时处理,差点造成P0事故

FullGC没及时处理,差点造成P0事故

使用JDK中自带的JVM分析工具解决内存溢出问题

使用JDK中自带的JVM分析工具解决内存溢出问题

【全网首发】一次想不到的 Bootstrap 类加载器带来的 Native 内存泄露分析

【全网首发】一次想不到的 Bootstrap 类加载器带来的 Native 内存泄露分析

18
0