本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序

腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云
这个标题原本有些长,“Thread.State: BLOCKED (on object monitor) at java.security.Provider.getService(Provider.java:680)”。我嫌它不利于搜索,所以给它改了。
这个问题,几乎是必现的。但是能遇到这个问题的人,不多。我在网上找了非常多的资料,都没有很好的解决办法。我这里分享一些思路,给遇到的朋友们。
"pool-2-thread-41001881" prio=10 tid=0x00007fc5a809a800 nid=0x2e80 waiting for monitor entry [0x00007fc560e5a000]
java.lang.Thread.State: BLOCKED (on object monitor)
at java.security.Provider.getService(Provider.java:680)
- locked <0x00000007531b5040> (a sun.security.provider.Sun)
at sun.security.jca.ProviderList.getService(ProviderList.java:331)
at sun.security.jca.GetInstance.getInstance(GetInstance.java:157)
at java.security.Security.getImpl(Security.java:695)
at java.security.MessageDigest.getInstance(MessageDigest.java:167)
这个问题的表现是,线程 BLOCKED。然后继续追踪 locked 的对象,你会发现,很多线程都在等待持有这个 locked 的对象。
"pool-2-thread-41001879" prio=10 tid=0x00007fc5a81ea000 nid=0x2e7e waiting for monitor entry [0x00007fc567da4000]
java.lang.Thread.State: BLOCKED (on object monitor)
at java.security.Provider.getService(Provider.java:680)
- waiting to lock <0x00000007531b5040> (a sun.security.provider.Sun)
at sun.security.jca.ProviderList.getService(ProviderList.java:331)
at sun.security.jca.GetInstance.getInstance(GetInstance.java:157)
at java.security.Security.getImpl(Security.java:695)
at java.security.MessageDigest.getInstance(MessageDigest.java:167)
然后,我通过工具,分享堆栈信息。https://fastthread.io/ft-error.jsp
结果表面,没有任何的死锁。只是有大量的线程处在 waiting for monitor entry 的状态。
一切的证据都指向java.security.Provider.getService
这个方法。查看其中的源码,确实有一个锁竞争synchronized
。
但是,网上基本上没有很多的解决办法。只是,很早之前,就有人反馈这里有性能问题,还给 jdk 提交了 bug,https://github.com/Backblaze/b2-sdk-java/issues/45。但是,官方不太承认,而且认为这个问题没那么严重,就这样一拖就是好几年。
官方的意思是,虽然这里有锁,存在性能问题,但是你们不能这样用。你们应该把一些东西缓存起来。话虽如此说,但是官方自有的类库中也没有对 getService 这个方法的耗时久的对象缓存起来。
反正,官方的意思就是,这个问题不紧急,出现概率低。好几年后,才在去年的 Java8 中的某个版本中修复了。利用了 ConcurrentHashMap 来解决并发问题。
官方说 JDK8 大于等于 8u241 以上的都被修复了,https://bugs.java.com/bugdatabase/view_bug.do?bug_id=7092821
但是经过我的验证并没有。我试最新的 8u401 的才有修复的代码。
在某些不便升级的场景,可以自行封装一部分底层 api。具体的做法,可以使用 ThreadLocal,或者是使用 ConcurrentHashMap。但是对于第三方 jar 包里的,就不好一一封装了。
更多疑难问题,参见我的知识星球https://t.zsxq.com/19IiYqST8。
参考资料
- https://github.com/Backblaze/b2-sdk-java/issues/45
- https://bugs.java.com/bugdatabase/view_bug.do?bug_id=7092821
- https://fastthread.io/
- https://groups.google.com/a/lists.datastax.com/g/java-driver-user/c/OVIwK1ZFd3A
- https://github.com/eclipse-californium/californium/pull/614
- https://github.com/eclipse-californium/californium/pull/614/files
最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号:xttblog2。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!
本文原文出处:业余草: » 记一次 JDK 底层 TLS 锁竞争性能问题