2016-06-17 21 views
16

Tôi gặp sự cố với System.exit(0);. Khi tôi thử đoạn code bên dưới kết quả là không có gì vì System.exit(0);:System.exit (0) không ngăn chặn cuối cùng được gọi khi có SecurityManager.checkExit ném một ngoại lệ

String number = "12345M"; 
try { 
    System.exit(0); 
} catch (Exception e) { 
    System.out.println("Exception caught"); 
} finally { 
    System.out.println("inside finally"); 
} 

Nhưng khi tôi cố gắng này bên dưới mã:

System.setSecurityManager(new SecurityManager() { 
    @Override 
    public void checkExit(int status) { 
     throw new ThreadDeath(); 
    } 
}); 

try { 
    System.exit(0); 
} finally { 
    System.out.println("I am finally block"); 
} 

Kết quả là:

Tôi cuối cùng chặn

Ai đó có thể hãy giải thích hành vi khác này?

+2

Nếu System.exit() bị ngăn cản làm điều đó là công việc bạn nên mong đợi nó doesn 't ngăn chặn cuối cùng từ được gọi là. –

Trả lời

18

exit bị ngăn bởi ThreadDeath ngoại lệ (mà không phải là một trong những bạn nên ném mình btw):

SecurityException - nếu một người quản lý an ninh tồn tại và phương pháp checkExit của nó không cho phép xuất cảnh với quy định trạng thái.

https://docs.oracle.com/javase/7/docs/api/java/lang/System.html#exit(int)

Lưu ý rằng bạn nên ném một SecurityException để ngăn chặn lối ra ví dụ:

System.setSecurityManager(new SecurityManager() { 
    @Override 
    public void checkExit(int status) { 
     throw new SecurityException("Not allowed."); 
    } 
}); 

try { 
    System.exit(0); 
} catch(SecurityException e) { 
    System.out.println("Exit failed."); 
} finally { 
    System.out.println("I am finally block"); 
} 
System.out.println("Program still running"); 

Output:

Exit failed. 
I am finally block 
Program still running 
3

Quoting:

Lớp java.lang.SecurityManager phép các ứng dụng để thực hiện một chính sách bảo mật. Nó cho phép ứng dụng xác định, trước khi thực hiện một hoạt động có thể không an toàn hoặc nhạy cảm, hoạt động là gì và liệu nó có đang được thực hiện trong một ngữ cảnh bảo mật cho phép thực hiện thao tác hay không. Ứng dụng có thể cho phép hoặc không cho phép thao tác.

Trong mã trên, kiểm traExit xác định xem thao tác có được phép hoạt động và bình thường hay không và do đó thoát. Vì một ngoại lệ được ném ra, do đó hoạt động được xác định là không an toàn và bị ngăn cản thực thi.

Vui lòng tham khảo http://www.tutorialspoint.com/java/lang/system_exit.htm

4

Khi bạn gọi System.exit() mà không trọng dụng phương pháp checkExit(), JVM phải dừng lại tại thời điểm đó và cuối cùng là không được gọi.

Tuy nhiên, khi bạn ghi đè phương thức checkExit(), ngoại lệ được ném và cuối cùng được gọi.

2

System.exit(0); là một gọi, nó sẽ gọi Runtime.exit sau đó và trong đó, nó sẽ kiểm tra xem một SecurityManager có được đính kèm hay không. Nếu một tệp được đính kèm, nó sẽ thực hiện phương thức checkExit.

xem mã trong Runtime.exit:

public void exit(int status) { 
    SecurityManager security = System.getSecurityManager(); 
    if (security != null) { 
     security.checkExit(status); 
    } 
    Shutdown.exit(status); 
} 

Vì vậy, trong mã của bạn hệ thống thực sự không thoát ra khi bạn gọi System.exit(0);, bởi vì bạn ném một ngoại lệ trong SecurityManager.checkExit

Các Shutdown.exit(status); không bao giờ được gọi và VM không dừng lại và nó sẽ tiếp tục thực hiện bất kỳ câu lệnh nào và sau đó nó sẽ kết thúc phương thức chính và chấm dứt.

Thay đổi bạn mã như thế này và chơi xung quanh

System.setSecurityManager(new SecurityManager() { 
           @Override 
           public void checkExit(int status) { 

            if(status == 0){ 
             System.out.println("Not going to finally"); 
            }else{ 
             throw new SecurityException(); 
            } 

           } 
          }); 

    try { 
     System.exit(1); 

    } catch (Exception e){ 
     e.printStackTrace(); 
    }finally { 
     System.out.println("I am finally block"); 
    } 

    System.out.println("System.exit(1) Didn't work ......"); 

} 

có một cái nhìn tại System.exit java doc và Runtime.exit doc

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