首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何诊断或检测Java静态初始化器中的死锁

如何诊断或检测Java静态初始化器中的死锁
EN

Stack Overflow用户
提问于 2014-12-18 15:09:49
回答 2查看 1.4K关注 0票数 12

(在Java中使用静态初始化器是否是一个好主意是超出了这个问题的范围。)

我在Scala应用程序中遇到了死锁,我认为这是由编译类中的互锁静态初始化器引起的。

我的问题是如何检测和诊断这些死锁--我发现当涉及静态初始化程序块时,用于死锁的常规JVM工具似乎不起作用。

下面是一个简单的示例Java应用程序,它在静态初始化程序中死锁:

代码语言:javascript
复制
public class StaticDeadlockExample implements Runnable
{
    static
    {
        Thread thread = new Thread(
                new StaticDeadlockExample(),
                "StaticDeadlockExample child thread");
        thread.start();
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args)
    {
        System.out.println("in main");
    }

    public static void sayHello()
    {
        System.out.println("hello from thread " + Thread.currentThread().getName());
    }

    @Override
    public void run() {
        StaticDeadlockExample.sayHello();
    }
}

如果你启动这个应用程序,它就死定了。死锁发生时的堆栈跟踪(来自jstack)包含以下两个死锁线程:

代码语言:javascript
复制
"StaticDeadlockExample child thread" prio=6 tid=0x000000006c86a000 nid=0x4f54 in Object.wait() [0x000000006d38f000]
   java.lang.Thread.State: RUNNABLE
    at StaticDeadlockExample.run(StaticDeadlockExample.java:37)
    at java.lang.Thread.run(Thread.java:619)

   Locked ownable synchronizers:
    - None

"main" prio=6 tid=0x00000000005db000 nid=0x2fbc in Object.wait() [0x000000000254e000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x000000004a6a7870> (a java.lang.Thread)
    at java.lang.Thread.join(Thread.java:1143)
    - locked <0x000000004a6a7870> (a java.lang.Thread)
    at java.lang.Thread.join(Thread.java:1196)
    at StaticDeadlockExample.<clinit>(StaticDeadlockExample.java:17)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:169)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:116)

   Locked ownable synchronizers:
    - None

我的问题如下

  1. 为什么第一个线程被标记为可运行,而实际上它正在等待一个锁?我能以某种方式检测到这个线程的“真实”状态吗?
  2. 为什么线程都没有被标记为拥有任何(相关的)锁,而事实上,其中一个持有静态的反式锁,而另一个则在等待它?我能以某种方式检测静态初始化程序锁所有权吗?
EN

回答 2

Stack Overflow用户

发布于 2014-12-18 21:10:52

Scala很容易落入陷阱。

简单的解决方法或诊断方法(如果您在堆栈跟踪中看到了斜面)是让您的对象扩展应用程序,让DelayedInit从静态初始化器中取出代码。

一些澄清的联系:

https://issues.scala-lang.org/browse/SI-7646

Scala:对象初始化器中的并行集合会导致程序挂起。

http://permalink.gmane.org/gmane.comp.lang.scala.user/72499

票数 1
EN

Stack Overflow用户

发布于 2016-11-14 11:23:13

我已经用我的工具尝试了这个例子,但它也未能检测到这是一个死锁。在与j控制台调试器进行了一些斗争并重新运行了这个示例几次之后,我注意到初始线程被标记为runnable,因为它是可运行的,这里的问题是,由于启动的线程访问了一个静态成员,这个操作在静态初始化程序块完成后排队(然而,在JVM规范中这个语义似乎并不清楚)。

静态初始化器没有完成,因为在这个奇怪的示例中,联接操作迫使它等待线程终止,但是我注意到,这个“排队”操作不会显式地或隐式地根据JVM规范获取锁。也许这本身不应该被认为是一个死锁,因为如果run方法的主体包含一个无限循环,情况也是一样的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27549671

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档