2009-02-05 36 views
22

Tôi là một tân binh Java và tôi đã tự hỏi, nếu tôi có mã Java điển hình sau đâyTrong Java, khối "cuối cùng" có được bảo đảm được gọi (trong phương thức chính) không?

public class MyApp { 
    public static void main(String[] args) { 
    try { 
     // do stuff 
    } catch { 
     // handle errors 
    } finally { 
     // clean up connections etc. 
    } 
    } 
} 

không JVM đảm bảo rằng các khối cuối cùng sẽ luôn luôn được chạy? Để hiểu nơi tôi đến từ, tôi đang sử dụng để C/C + + chương trình có thể chỉ sụp đổ nếu bạn dereference một con trỏ NULL và bạn không thể có bất kỳ mã để được chạy sau đó.

Nhưng như tôi hiểu Java và toàn bộ doanh nghiệp bộ nhớ GC/quản lý nói chung, không có điều gì như một dereferencing null con trỏ, tất cả mọi thứ là một khai thác dễ bắt, do đó, không thực sự là một cách để chương trình của tôi sụp đổ mà có thể làm cho nó bỏ qua cuối cùng, hay là có? Ví dụ: trong Python, tôi thường làm

try: 
    # do stuff 
except AnExceptionIKnewMightHappen: 
    # react in an appropriate way 
except: 
    # log that weird error I had not known could happen 

và tôi chưa bao giờ có bất kỳ ứng dụng nào bị chết mà không đi qua mã của tôi.

Tất nhiên, nếu hệ điều hành đối với một số lý do giết chết quá trình (hoặc nếu có điều gì giết chết toàn bộ hệ thống, như kéo phích cắm) không có nhiều Java có thể làm. Ngoài ra, từ PHP tôi biết các lỗi không thể bắt được mà bạn không thể bảo vệ chống lại, mặc dù thông dịch viên vẫn còn ở đó sau khi nó xảy ra (ít nhất nó có thể xuất ra một thông báo thích hợp).

Edit: Chỉ cần cho rõ ràng (nó đã không thực sự hiểu lầm bởi bất cứ ai), hãy để tôi nói thêm rằng tôi đang tìm kiếm những thứ bên trong mã của tôi mà có thể dẫn tới việc cuối cùng bị bỏ qua. Vì vậy, trỏ đến System.exit là một lời nhắc hữu ích, mặc dù tôi không thể thấy lý do tại sao tôi muốn làm một cái gì đó như thế.

Các JVM thoát là một cách khá rõ ràng và tôi muốn tính đó là một nguyên nhân bên ngoài. Những lưu ý chỉ ra rằng bạn cũng phải nhớ possibilty của đề thoát trong khi JVM và ứng dụng tiếp tục chạy was very helpful, bởi vì mặc dù nó cũng có vẻ hiển nhiên đối với tôi bây giờ, tôi đã không nghĩ đến nó.

+1

Gee, đó là câu trả lời nhanh. Rõ ràng là một câu hỏi rất noob. Dù sao cũng cảm ơn bạn! –

+0

Trả lời là không, xem chi tiết tại đây: http://tshikatshikaaa.blogspot.nl/2012/07/about-using-systemexit-in-try-catch.html – JVerstry

Trả lời

41

Về cơ bản có, ngoại trừ cho ghi chú listed here (tôi nhấn mạnh):

Nếu JVM thoát trong khi thử hoặc bắt đang đang được thực hiện, thì khối finally có thể không thực thi. Tương tự như vậy, nếu thread thực thi mã try hoặc catch bị gián đoạn hoặc bị hủy, thì khối cuối cùng có thể không thực hiện được ngay cả khi ứng dụng vẫn giữ nguyên trạng thái .

+15

Lưu ý rằng kéo dây nguồn thường là cách tốt để ngăn chặn "cuối cùng" cũng chạy ... –

+3

LOL - và nếu đó là laptop, pin trong laptop chết cùng lúc: D –

+5

Thả laptop ra khỏi câu chuyện trên cùng của một chiếc scraper trên bầu trời cũng ngăn chặn cả hai khối cuối cùng * và * tắt máy móc !! –

0

Erm, vâng :) Cho dù mã của bạn vào một nắm bắt hay không, cuối cùng sẽ chạy. Đó là một nơi tốt để đặt mã mà làm sạch sau khi thử.

Rõ ràng nó sẽ không chạy nếu bạn phá vỡ các JVM :)

0

Có, khối cuối cùng sẽ luôn được chạy, trừ khi có sự cố JVM (rất hiếm, nhưng điều đó có thể xảy ra).

12

Nó không được đảm bảo:

public class Main { 
    public static void main(String args[]) { 
     try { 
      System.out.println("try"); 
      System.exit(0); 
     } catch (Exception e) { 
      System.out.println("exception"); 
     } finally { 
      System.out.println("finally"); 
     } 
    } 
} 

Run đó.

+0

Không hoàn toàn chắc chắn về cách liên quan đến "do đó không thực sự là một cách để chương trình của tôi gặp sự cố có thể khiến chương trình bỏ qua cuối cùng hoặc ở đó?" Rõ ràng là nếu bạn thoát khỏi JVM, hãy powercycle hộp hoặc bắn màn hình, sau đó cuối cùng sẽ không chạy.Ngạc nhiên khi bỏ phiếu, nhưng có lẽ tôi chỉ ghen tị :) –

+0

Đó là bằng chứng đơn giản bằng counterexample. Rõ ràng nó không được bảo đảm. Điều đó có thể hoặc có thể không quan trọng đối với bạn. Và nếu nó xảy ra trên một lối ra "sạch", tôi đảm bảo với bạn nó không tốt hơn trên một vụ tai nạn thực sự. – cletus

+0

Tôi nghĩ rằng nó là an toàn để nói System.exit() là một trường hợp đặc biệt –

8

Trong một từ, có.

Mã trong khối finally trong Java luôn thực hiện, trừ khi:

  • Các JVM thoát trong thử hoặc khối catch
  • Các thread chạy mã bị gián đoạn hoặc bị giết trong thử hoặc khối catch

(từ: http://java.sun.com/docs/books/tutorial/essential/exceptions/finally.html)

Vì vậy, trừ khi bạn gọi một cách rõ ràng System.exit (int), hoặc giết chết quá trình hay một chủ đề bên ngoài, bạn có thể dựa vào nó.

3

Tuyệt đối, khối cuối cùng sẽ chạy, mọi lúc. Ngoại trừ trường hợp xảy ra sự cố JVM hoặc chức năng exit() đang được gọi. Tôi đã có mã nơi ứng dụng Java thực hiện các cuộc gọi đến mã nguồn gốc JNI bị phân đoạn. Kết quả là vụ tai nạn đã giết JVM và ngăn chặn việc chạy cuối cùng.

2

Chris Cameron là chính xác. Nhưng thông thường, một mã khóa finally được thực thi. Dullferece con trỏ không tồn tại trong Java:

try { 
    List<Object> x = null; 
    x.get(1); //throws the unchecked NullPointerException 
} finally { 
    //will be executed 
} 

Khối cuối cùng được thực thi.

+0

Điều đó thật thú vị, tôi không biết điều đó. Mặc dù nó vẫn hoàn toàn khác với một đoạn mã C cổ điển. –

1

Có, JVM luôn thực thi nó. Gaurranteed.

Tất nhiên ... nếu JVM chính nó chết (ví dụ: System.exit()), sau đó nó không ở vị trí để gaurrantee bất cứ điều gì. Nhưng JVM chết không phải là một vấn đề trong java.

+2

Điều này không đúng. ** Thread.stop() ** có thể ngăn chặn ** cuối cùng ** khối trong khi JVM vẫn chạy. –

0

ngoại lệ duy nhất cuối cùng chặn không được thực hiện là, hoặc JVM gặp sự cố hoặc system.exit().

+0

Tôi nghĩ rằng cuối cùng các khối được gọi khi 'System.exit()' được gọi. –

0

Có vẻ như khá rõ ràng rằng không có gì nhiều thứ khác sẽ chạy sau khi JVM thoát hoặc sẽ chạy mã trong chuỗi bị xóa đó. Rõ ràng. Vì vậy, khi JVM đang chạy, mọi mã sẽ chạy, sẽ chạy và sau khi JVM thoát hoặc bên trong một chuỗi chết, không có gì sẽ chạy, ngay cả bất kỳ loại mã nào. Vì vậy, không có cách nào để ngăn chặn, nhưng nếu có nhu cầu về mệnh đề cuối cùng, hãy đặt nó.

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