2013-04-04 32 views
6

Tôi vừa mới chuyển từ Oracle JDK 1.6, để mở JDK 1.7.0_03, và tôi đã trúng một bế tắc khá đáng chú ý xuất cảnh:System.exit không phải là luồng an toàn trên Linux?

java.lang.Thread.State: WAITING (on object monitor) 
at java.lang.Object.wait(Native Method) 
at java.lang.Thread.join(Thread.java:1258) 
- locked <0x8608dda0> (a sun.awt.X11.XToolkit$1$1) 
at java.lang.Thread.join(Thread.java:1332) 
at java.lang.ApplicationShutdownHooks.runHooks(ApplicationShutdownHooks.java:106) 
at java.lang.ApplicationShutdownHooks$1.run(ApplicationShutdownHooks.java:46) 
at java.lang.Shutdown.runHooks(Shutdown.java:123) 
at java.lang.Shutdown.sequence(Shutdown.java:167) 
at java.lang.Shutdown.exit(Shutdown.java:212) 
- locked <0x8603df28> (a java.lang.Class for java.lang.Shutdown) 
at java.lang.Runtime.exit(Runtime.java:107) 
at java.lang.System.exit(System.java:960) 

Có vẻ như bạn phải gọi System.exit từ AWT hàng đợi sự kiện. Điều này là thật? Không có tài liệu nào về yêu cầu luồng trong tài liệu Sun Runtime.exit

Tôi đã nhấn các trường hợp đáng ngạc nhiên khác khi yêu cầu khóa cây AWT chỉ được yêu cầu trên Linux, nhưng cái này lấy bánh. Đây có phải là một lỗi, hoặc có tôi chỉ bỏ lỡ một cái gì đó trong tài liệu?

+2

Có một SSCCE (http://sscce.org/) chứng minh bế tắc? – NPE

+0

Phương thức 'System.exit' buộc chấm dứt tất cả các luồng trong máy ảo Java. Bạn không sửa chữa vấn đề bế tắc được đề cập bằng cách sử dụng System.exit, bạn đang dừng chương trình trước khi bế tắc xảy ra. Khi bạn dừng lại bình thường, các chủ đề khác của bạn tiếp tục mà không cần sự hỗ trợ của sợi chính và dường như chúng không thể làm như vậy mà không có nó. –

Trả lời

1

Tùy thuộc, phương thức runHooks sẽ bắt đầu bất kỳ chủ đề móc nào được đăng ký thông qua Runtime.addShutdownHook và đợi cho đến khi hoàn tất. Nếu bất kỳ chủ đề móc nào của bạn đang khóa một số tài nguyên mà chuỗi sự kiện AWT cũng yêu cầu, chúng có thể gây ra khóa chết.

Nếu bạn phải gọi System.exit trong AWT chủ đề sự kiện của bạn, tôi đề nghị bạn gọi nó trong một chủ đề như:

new Thread(){ 
      public void run() { 
       System.exit(0); 
      } 
    }.start(); 
+0

Tôi thích đoạn mã này. Nó thực sự là một điều đẹp. Cảm ơn. –

1

Nó là không thể nói cho dù đây là một lỗi trong thời gian chạy mà không biết nhiều hơn về những gì ứng dụng đang làm (lý tưởng, điều này sẽ có dạng SSCCE). Ví dụ:

Ví dụ: dưới đây thể hiện một bế tắc tương tự liên quan đến System.exit(). Tuy nhiên, rõ ràng là một lỗi trong ứng dụng, không phải là trong số System.exit():

public class OhNo { 

    final static Object lock = new Object(); 

    public static void main(String[] args) { 
     new Thread(new Runnable() { 
      public void run() { 
       synchronized (lock) { 
        for (;;) { 
        } 
       } 
      } 
     }).start(); 
     Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { 
      public void run() { 
       synchronized (lock) { 
        System.out.println("in shutdown hook"); 
       } 
      } 
     })); 
     System.out.println("about to call System.exit()"); 
     System.exit(0); 
    } 
} 
+0

AWT-EventQueue-0 đang gọi cho tôi, và tôi đang lấy một khóa trên một đối tượng O. O đang bận nên AWT-EventQueue-0 bị chặn chờ. O đang gọi System.exit(), và trên Linux, điều này chờ đợi cho khóa cây AWT, mà, tất nhiên, đang chờ đợi trên O. Do đó, bế tắc. Dù sao, tôi đoán cho rằng có những móc tắt mà có thể làm bất kỳ điều kỳ lạ, câu trả lời đúng là tạo ra một sợi mới để đóng cửa, theo đề nghị của Spring.Rush. Điều đó có vẻ rất mạnh mẽ. –

Các vấn đề liên quan