【问题标题】:Java OSX MessageDigest.getInstance("MD5") hangsJava OSX MessageDigest.getInstance("MD5") 挂起
【发布时间】:2014-04-21 15:16:52
【问题描述】:

我目前在将 Java 代码部署到 OSX 时遇到问题。根据我的调试日志,这一行:

m = MessageDigest.getInstance("MD5");

有时只是没有完成执行。它不返回。应用程序一直在消耗 CPU。这在应用程序启动期间非常早,所以没有 GUI 窗口,但已经有 2 个线程尝试执行 md5 散列 - 也许以某种方式进行交互?我从我们的用户那里得到的唯一报告是“应用程序有时无法启动”。这是相当随机的,大约 10 次发生 3 次。

这是一些已知问题吗?我是否以错误的方式初始化某些东西?我注意到有人提到 MessageDigest 类不是线程安全的,但是将整个有问题的代码放在同步函数中并不能解决问题。有什么想法吗?

Java 1.6.0_45 64 位,在 Mac OS X 10.6.8 上运行

编辑:按照 Oleg 的想法,我抓取了所有过程的堆栈跟踪:

    "Thread-4" daemon prio=5 tid=1130d6000 nid=0x1006d8000 waiting for monitor entry [00000000]
   java.lang.Thread.State: BLOCKED (on object monitor)

"AWT-Shutdown" prio=5 tid=113b1c000 nid=0x11b616000 in Object.wait() [11b615000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <7e1f45168> (a java.lang.Object)
    at java.lang.Object.wait(Object.java:485)
    at sun.awt.AWTAutoShutdown.run(AWTAutoShutdown.java:265)
    - locked <7e1f45168> (a java.lang.Object)
    at java.lang.Thread.run(Thread.java:680)

"AWT-AppKit" daemon prio=5 tid=1139db000 nid=0x7fff70596cc0 waiting for monitor entry [00000000]
   java.lang.Thread.State: BLOCKED (on object monitor)

"Thread-1" prio=5 tid=113962000 nid=0x11b293000 waiting for monitor entry [11b290000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at java.lang.Runtime.loadLibrary0(Runtime.java:815)
    - waiting to lock <7e1e04f80> (a java.lang.Runtime)
    at java.lang.System.loadLibrary(System.java:1045)
    at sun.security.pkcs11.wrapper.PKCS11$1.run(PKCS11.java:88)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.security.pkcs11.wrapper.PKCS11.<clinit>(PKCS11.java:86)
    at sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:281)
    at sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:86)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at sun.security.jca.ProviderConfig$4.run(ProviderConfig.java:262)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.security.jca.ProviderConfig.doLoadProvider(ProviderConfig.java:244)
    at sun.security.jca.ProviderConfig.getProvider(ProviderConfig.java:224)
    - locked <7e1e3a020> (a sun.misc.Launcher$AppClassLoader)
    at sun.security.jca.ProviderList.getProvider(ProviderList.java:215)
    at sun.security.jca.ProviderList.getService(ProviderList.java:313)
    at sun.security.jca.GetInstance.getInstance(GetInstance.java:140)
    at java.security.Security.getImpl(Security.java:659)
    at java.security.MessageDigest.getInstance(MessageDigest.java:129)
    at pl.gizarma.starter2.util.MD5.getMD5Bytes(MD5.java:23)
    - locked <7fb495f30> (a java.lang.Class for pl.gizarma.starter2.util.MD5)
    at pl.gizarma.starter2.util.MD5.fromBytes(MD5.java:14)
    at pl.gizarma.starter2.util.MD5.fromString(MD5.java:9)
    at pl.gizarma.starter2.net.UrlCache.getUrl(UrlCache.java:69)
    - locked <7e1fb2600> (a pl.gizarma.starter2.net.UrlCache)
    at pl.gizarma.starter2.net.UrlCache.getUrl(UrlCache.java:61)
    at pl.gizarma.starter2.net.RetryingUrlReader.readUseCache(RetryingUrlReader.java:75)
    at pl.gizarma.starter2.net.RetryingUrlReader.read(RetryingUrlReader.java:60)
    at pl.gizarma.starter2.net.UpdateDownloader.download(UpdateDownloader.java:29)
    at pl.gizarma.starter2.job.UpdateJob.run(UpdateJob.java:20)
    at pl.gizarma.starter2.Starter2Main$1.run(Starter2Main.java:51)

"Low Memory Detector" daemon prio=5 tid=113035000 nid=0x11af39000 runnable [00000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" daemon prio=9 tid=113034800 nid=0x11ae36000 waiting on condition [00000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" daemon prio=9 tid=113033800 nid=0x11ad33000 waiting on condition [00000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" daemon prio=9 tid=113033000 nid=0x11ac30000 waiting on condition [00000000]
   java.lang.Thread.State: RUNNABLE

"Surrogate Locker Thread (Concurrent GC)" daemon prio=5 tid=113032000 nid=0x11ab2d000 waiting on condition [00000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" daemon prio=8 tid=11387d000 nid=0x11aa2a000 in Object.wait() [11aa29000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <7e1e01300> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
    - locked <7e1e01300> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
    at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:171)

"Reference Handler" daemon prio=10 tid=113029000 nid=0x11a7cb000 in Object.wait() [11a7ca000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <7e1e011d8> (a java.lang.ref.Reference$Lock)
    at java.lang.Object.wait(Object.java:485)
    at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
    - locked <7e1e011d8> (a java.lang.ref.Reference$Lock)

"main" prio=5 tid=113800800 nid=0x1017fb000 runnable [1017f8000]
   java.lang.Thread.State: RUNNABLE
    at java.lang.ClassLoader$NativeLibrary.load(Native Method)
    at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1827)
    - locked <7e1e010a8> (a java.util.Vector)
    - locked <7e1e01100> (a java.util.Vector)
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1724)
    at java.lang.Runtime.loadLibrary0(Runtime.java:823)
    - locked <7e1e04f80> (a java.lang.Runtime)
    at java.lang.System.loadLibrary(System.java:1045)
    at sun.security.action.LoadLibraryAction.run(LoadLibraryAction.java:50)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.awt.NativeLibLoader.loadLibraries(NativeLibLoader.java:38)
    at sun.awt.DebugHelper.<clinit>(DebugHelper.java:29)
    at java.awt.Component.<clinit>(Component.java:566)
    at pl.gizarma.starter2.Starter2Main.prepareMainFrame(Starter2Main.java:23)
    at pl.gizarma.starter2.Starter2Main.main(Starter2Main.java:17)

"VM Thread" prio=9 tid=113024800 nid=0x11a927000 runnable 

"Gang worker#0 (Parallel GC Threads)" prio=9 tid=113802000 nid=0x112dc4000 runnable 

"Gang worker#1 (Parallel GC Threads)" prio=9 tid=113802800 nid=0x112ec7000 runnable 

"Concurrent Mark-Sweep GC Thread" prio=9 tid=11384d000 nid=0x11a498000 runnable 
"VM Periodic Task Thread" prio=10 tid=113897000 nid=0x11b03c000 waiting on condition 

"Exception Catcher Thread" prio=10 tid=113801800 nid=0x112c01000 runnable 
JNI global references: 1004

Heap
 par new generation   total 19136K, used 3772K [7e1e00000, 7e32c0000, 7e4790000)
  eden space 17024K,  22% used [7e1e00000, 7e21af1b8, 7e2ea0000)
  from space 2112K,   0% used [7e2ea0000, 7e2ea0000, 7e30b0000)
  to   space 2112K,   0% used [7e30b0000, 7e30b0000, 7e32c0000)
 concurrent mark-sweep generation total 63872K, used 0K [7e4790000, 7e85f0000, 7fae00000)
 concurrent-mark-sweep perm gen total 21248K, used 7162K [7fae00000, 7fc2c0000, 800000000)

引用的 MessageDigest.getInstance("MD5") 导致 System.loadLibrary,即“等待锁定 ”。 7e1e04f80 被另一个 System.loadLibrary 调用锁定 - 从 java.awt.Component. 开始,这意味着或多或少超出了我的控制范围。锁定线程正在执行本机例程 $NativeLibrary.load,它似乎已挂起。我不知道正在加载什么库。

有什么想法吗?

【问题讨论】:

  • 你需要在它发生时获取线程转储,它显然会显示发生了什么。查看this 和链接的问题,了解获取 java 线程转储的不同方式。
  • 我认为最好为每个线程创建一个新的 MessageDigest 实例,而不是同步您的摘要方法。
  • @OlegEstekhin 感谢您的建议,我用完整的线程转储更新了答案。
  • 检查this question - 最后一个答案表明,如果您可以强制 AWT 先加载本机库,则可以解决死锁。值得一试。
  • 我很高兴你在我和@idolon cmets 的帮助下解决了这个问题,但我觉得这些 cmets 本身并不是答案。您绝对应该从另一个问题中投票给answer,您可以手动将赏金奖励给所有相关方。

标签: java multithreading macos md5


【解决方案1】:

来自堆栈跟踪

“Thread-1”prio=5 tid=113962000 nid=0x11b293000 等待监视器条目 [11b290000] java.lang.Thread.State: BLOCKED (在对象监视器上) 在 java.lang.Runtime.loadLibrary0(Runtime.java:815) - 等待锁定 (一个 java.lang.Runtime) 在 java.lang.System.loadLibrary(System.java:1045) 在 sun.security.pkcs11.wrapper.PKCS11$1.run(PKCS11.java:88)

PKCS#11 是一种模块标准,通常用于访问智能卡和其他硬件加密设备。看起来您的应用程序在加载 PKCS#11 模块时挂起。 PKCS#11 驱动程序由第三方提供,我很遗憾地说,但根据我的经验,它经常出现错误且不稳定。如果您的应用程序不需要访问加密硬件,我建议禁用 PKCS#11。

for(Provider p: Security.getProviders())
    if(p instanceof sun.security.pkcs11.SunPKCS11)
        Security.removeProvider(p.getName());

另见:

【讨论】:

  • 正如我在答案下评论的那样 - “我认为它不是为挂起的 PKCS#11 加载本机库,而是加载 AWT 所需的东西。由 MessageDigest.getInstance() 触发的加载永远不会到达本机调用,因为它等待互斥锁释放。我需要调查正在为 AWT 加载的库以及它挂起的原因”。不过感谢您的尝试 :) 我目前正计划调查 Oleg 的建议。
猜你喜欢
  • 1970-01-01
  • 2014-05-11
  • 2011-12-09
  • 1970-01-01
  • 1970-01-01
  • 2013-08-21
  • 1970-01-01
  • 2012-08-23
  • 1970-01-01
相关资源
最近更新 更多