2016-06-22 57 views
2

我有以下三个类。在java代码中获取死锁

BaseClass.java

public class BaseClass { 

    static { 
     load(); 
    } 

    public static void init() { 
     System.out.println("base init"); 
    } 

    private static void load() { 
     System.out.println("In load method of base class"); 
     DerivedClass dc = new DerivedClass(); 
     System.out.println("Object creation done."); 
    } 

} 

DerivedClass.java

public class DerivedClass extends BaseClass { 

    public DerivedClass() { 
     System.out.println("derived class constructor"); 
    } 

    public static boolean isSynthetic(String _attr) { 
     return true; 
    } 
} 

Helper.java

public class Helper { 

    public static void main(String[] args) { 
     Thread t = new Thread() { 
      public void run() { 
       BaseClass.init(); 
      }; 
     }; 
     t.start(); 
     System.out.println("calling static method of derived class.."); 
     System.out.println(DerivedClass.isSynthetic("test")); 
    } 

} 

当我执行从Helper.java主要方法,我得到以下输出 -

调用派生类的静态方法..

在基类

的负载方法此执行之后是停止但过程仍在运行。 所以看起来有一些僵局,但我不明白这是为什么。 需要帮助。

+0

下面的链接回答你的问题。 [http://stackoverflow.com/questions/10698516/behavior-of-static-blocks-with-inheritance](http://stackoverflow.com/questions/10698516/behavior-of-static-blocks-with-inheritance ) –

回答

2

当第一次引用BaseClass时,类加载器启动并想要设置该类以供使用。所以它加载类,并开始静态初始化块

static { 
    load(); 
} 

这将调用load - 方法有你尝试创建DerivedClass类型的对象。这将首先尝试调用super()-构造器,即类BaseClass的方法 - 但BaseClass尚未完全初始化,因为它的静态初始化器尚未完成=>死锁。

编辑: 根据您的意见,我做了一些更多的研究。事实上,事情并不像我想象的那么简单。 JVM能够处理递归初始化,所以在单线程情况下没有问题。有关类初始化过程的描述可以在JVM规范的5.5节中找到。

这里的罪魁祸首实际上是两个初始化过程之间的竞争条件。

线程1达到DerivedClass.isSynthetic("test"),并开始初始化DerivedClass

同时线程2到达BaseClass.init()并开始初始化BaseClass。当初始化DerivedClass线程1认识到它必须初始化超类。由于线程2已经在进行BaseClass的初始化,线程1必须等待它完成。当初始化线程2达到DerivedClass dc = new DerivedClass();。由于线程1已经在进行DerivedClass的初始化,所以线程2必须等待它完成。

所以实际上这是一个典型的死锁,其中两个线程尝试按不同顺序输入两个关键代码路径(“类X的初始化”)(BaseClass-> DerivedClass vs.DerivedClass-> BaseClass)并最终等待对方。

在适当的地方添加一些Thread.sleep(100);也会告诉你这是一个真正的竞赛条件。在我的测试过程中,有时程序完成成功,尽管在初始化过程中存在循环依赖。

+0

你的解释似乎是可能的,但是为什么'System.out.println(DerivedClass.isSynthetic(“test”));'这里派生类的静态方法也处于死锁状态。当我删除派生类的静态方法的调用,然后执行工作正常,我得到的输出为:
调用 在基类 派生类构造函数 完成对象创建。 base init –

+0

@Rahulkhandelwal你说得对,JVM比我想象的更复杂。我为真正的原因添加了一些解释。 –

+0

感谢您的解释。这真的很有帮助。 –