Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何诊断或检测Java静态初始化器中的死锁_Java_Scala_Deadlock - Fatal编程技术网

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

如何诊断或检测Java静态初始化器中的死锁,java,scala,deadlock,Java,Scala,Deadlock,(在Java中使用静态初始值设定项是否是一个好主意超出了这个问题的范围。) 我在Scala应用程序中遇到死锁,我认为这是由编译类中的联锁静态初始值设定项引起的 我的问题是如何检测和诊断这些死锁——我发现当涉及静态初始化程序块时,用于死锁的普通JVM工具似乎不起作用 下面是一个简单的Java应用程序示例,它在静态初始值设定项中死锁: public class StaticDeadlockExample implements Runnable { static { T

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

我在Scala应用程序中遇到死锁,我认为这是由编译类中的联锁静态初始值设定项引起的

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

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

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
)包含以下两个死锁线程:

"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
对象中的“静态死锁示例子线程”prio=6 tid=0x000000006c86a000 nid=0x4f54.wait()[0x000000006d38f000] java.lang.Thread.State:可运行 在StaticDeadlockExample.run(StaticDeadlockExample.java:37) 运行(Thread.java:619) 锁定可拥有的同步器: -没有 Object.wait()中的“main”prio=6 tid=0x00000000005db000 nid=0x2fbc[0x000000000254e000] java.lang.Thread.State:正在等待(在对象监视器上) 在java.lang.Object.wait(本机方法) -等待(一个java.lang.Thread) 位于java.lang.Thread.join(Thread.java:1143) -锁定(一个java.lang.Thread) 位于java.lang.Thread.join(Thread.java:1196) 在StaticDeadlockExample。(StaticDeadlockExample.java:17) 位于java.lang.Class.forName0(本机方法) 位于java.lang.Class.forName(Class.java:169) 位于com.intellij.rt.execution.application.AppMain.main(AppMain.java:116) 锁定可拥有的同步器: -没有 我的问题如下

  • 为什么第一个线程标记为RUNNABLE,而实际上它正在等待一个锁?我能检测出这个线程的“真实”状态吗
  • 为什么两个线程都没有标记为拥有任何(相关)锁,而实际上一个线程持有静态初始化器锁,另一个线程正在等待它?我可以检测静态初始值设定项锁的所有权吗

  • Scala很容易落入陷阱

    简单的解决方法或诊断方法(如果您在堆栈跟踪中看到clinit)是让您的对象扩展应用程序,让DelayedInit将您的代码从静态初始值设定项中删除

    一些澄清链接:


    我尝试了这个示例,但它也未能将其检测为死锁。在与jconsole调试器进行了一些斗争并重新运行了几次示例后,我注意到初始线程被标记为可运行,因为它是可运行的,这里的问题是,由于启动的线程访问静态成员,所以在完成静态初始值设定项块后,此操作将排队(这一语义在中不清楚,但似乎是这样)


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

    为什么您认为它在等待锁?如果它在等待锁,它会(1)处于等待状态,不可运行和(2),会提到“等待…”或“等待锁定”在堆栈的顶部条目之后。我认为它们不可见。它们是由JVM专门为此进程管理的。可能线程转储没有显示它们。@Dima--我知道它正在等待锁,因为我构造代码是为了这样做的。如果你运行上面的程序,它将永远死锁--你自己试试。这是你的观点吗它没有使用
    java.util.concurrent.locks
    ?如果是的话——这是对的,但不是很有帮助。@SotiriosDelimanolis是的,锁在线程转储中似乎不可见。问题中有一个工作示例演示了这一事实。我的问题是如何使它们可见。这是一个非常有趣的问题,但在examp中le有点…差。初始化器用于初始化静态,但这里的初始化器不仅被滥用来运行业务逻辑,还被滥用来启动单独的线程。差,差的JVM。谢谢。你知道是否可以检测到这些死锁吗?线程被列为可运行,而隐式静态锁没有列在loc中ks由线程拥有。虽然它没有被记录为锁,但它的行为与锁完全一样。我认为它是一个“秘密”内部锁,JVM不允许userland与之交互或检查。我认为,如果说它没有被记录为锁,它不可能是死锁,那么定义问题就是欺骗。“初始线程被标记为可运行,因为它是可运行的”--在这个词的正常含义中它不是可运行的,它在等待隐藏的静态初始值设定项锁时被阻止。我的问题是1)如何检测线程处于该状态,以及2)如何检测它正在等待的静态初始值设定项?我强烈怀疑这两个问题的答案都是“您不能,因为JVM没有公开此信息”