java.security.provider.getservice blocked
JDK版本:
JDK8u192
bug:
https://bugs.openjdk.org/browse/JDK-8206333
堆栈:
"Common-Business-Thread-572" Id=1723 BLOCKED
at java.security.Provider.getService(Provider.java:1035)
at sun.security.jca.ProviderList.getService(ProviderList.java:332)
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)
at net.rubyeye.xmemcached.HashAlgorithm.computeMd5(HashAlgorithm.java:204)
at net.rubyeye.xmemcached.HashAlgorithm.hash(HashAlgorithm.java:133)
at net.rubyeye.xmemcached.impl.KetamaMemcachedSessionLocator.getSessionByKey(KetamaMemcachedSessionLocator.java:200)
at net.rubyeye.xmemcached.XMemcachedClient.catalogKeys(XMemcachedClient.java:1219)
at net.rubyeye.xmemcached.XMemcachedClient.getMulti0(XMemcachedClient.java:1156)
at net.rubyeye.xmemcached.XMemcachedClient.get(XMemcachedClient.java:1055)
at net.rubyeye.xmemcached.XMemcachedClient.get(XMemcachedClient.java:1088)
"Common-Business-Thread-119" Id=255 BLOCKED
at java.security.Provider.getService(Provider.java:1035)
at sun.security.jca.ProviderList.getService(ProviderList.java:332)
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)
at org.apache.commons.codec.digest.DigestUtils.getDigest(DigestUtils.java:68)
at org.apache.commons.codec.digest.DigestUtils.getMd5Digest(DigestUtils.java:98)
at org.apache.commons.codec.digest.DigestUtils.md5(DigestUtils.java:260)
at org.apache.commons.codec.digest.DigestUtils.md5Hex(DigestUtils.java:296)
问题分析:
- 频繁调用了MessageDigest.getInstance,就会调用Provider.getService (有synchronized关键字)
- DigestUtils.md5Hex 每次调用都会去调用MessageDigest.getInstance,而HashAlgorithm.computeMd5则是只有线程第一次计算MD5,才会去调用MessageDigest.getInstance
目前解决方案:
- 升级JDK版本 参考:https://bugs.java.com/bugdatabase/view_bug.do?bug_id=7092821 (建议这一步,但是高版本jdk要收费)
- 优化DigestUtils,效仿HashAlgorithm.computeMd5,把MessageDigest 存到去线程变量中,减少MessageDigest.getInstance调用
代码调整:
// DigestUtils.md5Hex 变成Hex.encodeHexString(HashAlgorithm.computeMd5)
@Test
public void test() {
String data = "HELLO WORLD";
String expect = DigestUtils.md5Hex(data);
//
byte[] bytes = HashAlgorithm.computeMd5(data);
String actual = Hex.encodeHexString(bytes);
Assert.assertEquals(expect, actual);
}