Tôi đang sử dụng API được cấp phép có phương thức lấy/phát hành đối tượng giấy phép từ máy chủ cấp phép có số lượng giấy phép hữu hạn. Khi bắt đầu ứng dụng của tôi, tôi gọi phương thức để có được giấy phép, nhưng tôi muốn đảm bảo rằng điều này được phát hành ngay cả khi chương trình của tôi chấm dứt/treo đột ngột (ngoại lệ, SIGTERM, v.v.). Móc tắt máy có phải là cách tốt nhất để tiếp cận vấn đề này không?Làm thế nào để đảm bảo một đoạn mã được chạy trước khi thoát khỏi ứng dụng java
Trả lời
@thedan là đúng về tai nạn JVM cứng. Nếu JVM gặp khó khăn hoặc nó bị SIGKILL, nó sẽ không có cơ hội chạy bất cứ thứ gì trước khi thoát. Không có gì bạn có thể làm để khắc phục điều này trong Java trong kịch bản đó. (Nhưng tình hình cũng giống nhau ở các ngôn ngữ khác nữa ...)
Tuy nhiên nếu JVM thực hiện tắt máy theo thứ tự để đáp ứng tất cả các chủ đề không chấm dứt, hãy gọi System.exit(), nhận SIGINT, v.v. , sau đó JVM sẽ cố gắng chạy các móc tắt máy. Có thêm thông tin về các cơ chế móc tắt của Java trong trang Q&A và javadocs.
Cách tiếp cận finally
cũng là một tùy chọn, nhưng chỉ hoạt động nếu chuỗi được đề cập bị chấm dứt trước khi JVM thoát. Điều này sẽ không xảy ra nếu System.exit()
được gọi hoặc JVM bị chấm dứt bởi một tín hiệu. Shutdown hooks làm việc trong nhiều tình huống hơn.
(Theo ý mình, finally
thực sự để thực hiện sạch trên một chuỗi đơn chứ không phải cho toàn bộ ứng dụng. Tuy nhiên, nếu ứng dụng của bạn chỉ bao gồm một chuỗi ... hoặc nếu nó có chuỗi chủ có trách nhiệm theo thứ tự tắt máy ... sau đó finally
có thể phục vụ mục đích dọn dẹp ứng dụng.)
Giải pháp thực tế là định cấu hình API được cấp phép để người quản lý giấy phép có thể phát hiện khi bản sao ứng dụng sử dụng giấy phép biến mất mà không phát hành. Cho dù điều này là có thể phụ thuộc vào người quản lý giấy phép.
Nếu chương trình được chấm dứt thông qua sự cố của JVM, bạn không thể dựa vào bất cứ điều gì được gọi.
Nếu chương trình được chấm dứt thông qua một ngoại lệ không liên quan đến JVM, bạn sẽ có thể bao bọc mọi thứ trong khối try/catch/finally. Bất kỳ mã nào trong khối cuối cùng sẽ được đảm bảo chạy trước khi mã của bạn thoát.
Đối với trường hợp ngoại lệ, bạn có thể quấn phần thân của main
trong một try/catch/block
. Để xử lý tín hiệu SIGTERM
, bạn có thể add a shutdown hook. Tuy nhiên, móc tắt máy không được đảm bảo để kích hoạt tín hiệu như SIGKILL
.
Từ Java doc:
Trong trường hợp hiếm hoi các máy ảo có thể hủy bỏ, đó là, dừng chạy mà không cần tắt sạch. Điều này xảy ra khi máy ảo bị chấm dứt bên ngoài, ví dụ với tín hiệu
SIGKILL
trên Unix hoặc cuộc gọiTerminateProcess
trên Microsoft Windows. Máy ảo cũng có thể hủy nếu phương pháp gốc bị lỗi, ví dụ: làm hỏng cấu trúc dữ liệu nội bộ hoặc cố truy cập bộ nhớ không tồn tại. Nếu máy ảo hủy bỏ thì không đảm bảo có thể được thực hiện về việc có hay không bất kỳ móc tắt máy nào sẽ được chạy.
bạn đạt được điều này bằng cách không bao giờ gọi Sytem.exit(). Trong main() bạn tạo một "dòng cuối cùng của quốc phòng" với
try {
startApp();
} catch (Exception ex) {
// do some logging
} finally {
releaseLicense();
}
Ý của bạn là một mệnh đề 'cuối cùng'? –