Có phải * bao giờ * ổn khi bắt StackOverflowError trong Java không?


27

Tôi đã từng nghĩ rằng nó không phải, nhưng hôm qua tôi phải làm điều đó. Đây là một ứng dụng sử dụng Akka (một triển khai hệ thống tác nhân cho JVM) để xử lý các công việc không đồng bộ. Một trong những diễn viên thực hiện một số thao tác PDF và vì thư viện bị lỗi, nên StackOverflowErrormọi lúc mọi nơi đều chết .

Khía cạnh thứ hai là Akka được cấu hình để tắt toàn bộ hệ thống diễn viên của nó nếu có bất kỳ lỗi nghiêm trọng nào của JVM (ví dụ StackOverflowError) bị bắt.

Khía cạnh thứ ba là hệ thống diễn viên này được nhúng bên trong một ứng dụng web (đối với WTF-ish, di sản, lý do), vì vậy khi hệ thống diễn viên bị tắt, ứng dụng web không hoạt động. Hiệu quả ròng là trên một StackOverflowErrorứng dụng xử lý công việc của chúng tôi trở thành một ứng dụng web trống.

Như một cách khắc phục nhanh, tôi đã phải bắt quả tang StackOverflowError, để nhóm chủ đề của hệ thống diễn viên không bị phá hủy. Điều này khiến tôi nghĩ rằng đôi khi có thể gặp phải những lỗi như vậy, đặc biệt là trong những bối cảnh như thế này? Khi có một nhóm xử lý các tác vụ tùy ý? Không giống như OutOfMemoryErrortôi không thể tưởng tượng làm thế nào một người StackOverflowErrorcó thể để một ứng dụng ở trạng thái không nhất quán. Ngăn xếp bị xóa sau một lỗi như vậy, vì vậy tính toán có thể tiếp tục bình thường. Nhưng có lẽ tôi đang thiếu một cái gì đó quan trọng.

Ngoài ra, hãy lưu ý rằng tôi là tất cả để sửa lỗi ngay từ đầu (vì thực tế tôi đã sửa một SOE trong cùng ứng dụng này vài ngày trước), nhưng tôi thực sự không biết khi nào loại tình huống có thể phát sinh.

Tại sao nên khởi động lại quy trình JVM thay vì bắt StackOverflowError, đánh dấu công việc đó là thất bại và tiếp tục với công việc của tôi?

Có bất kỳ lý do thuyết phục để không bao giờ bắt các doanh nghiệp nhà nước? Ngoại trừ "thực hành tốt nhất", đó là một thuật ngữ mơ hồ không cho tôi biết gì.


1
một tùy chọn khác là tăng không gian ngăn xếp có sẵn trên JVM
ratchet freak

3
@ratchetfreak: StackOverflowExceptions thường là do một chuỗi các cuộc gọi phương thức không kết thúc - tăng không gian ngăn xếp sau đó sẽ làm tăng chi phí bộ nhớ của một luồng mới mà không có lợi ích.
jhominal

1
Ít nhất một SOE là hợp pháp vì đầu vào rất lớn. Thật không may, xử lý nó bằng một triển khai đệ quy (hàm regex của Java) không phải là một ý kiến ​​hay. Dù sao, ngay cả khi tính toán được đảm bảo chấm dứt, bạn không biết liệu kích thước ngăn xếp mới có đủ lớn cho các tính toán khác hay không.
Ionuț G. Stan

2
Điều này không nên được di chuyển đến Sta ... Oh, đợi đã ... đừng bận tâm. :-)
Blrfl

Về thư viện lỗi của bạn. Bạn nên thực sự di chuyển chức năng thao tác pdf đó vào quy trình riêng của mình để bạn có thể để os giết nó.
Esben Skov Pedersen

Câu trả lời:


44

Theo nguyên tắc chung, nếu hoàn toàn không bao giờ, có thể chấp nhận làm điều gì đó và có thỏa thuận về điều đó, những người thực hiện ngôn ngữ sẽ không cho phép điều đó. Hầu như không có câu châm ngôn rõ ràng nhất trí như vậy. (May mắn thay, vì đó là những gì giúp chúng ta lập trình viên con người trong công việc!)

Có vẻ như bạn đã tìm thấy một tình huống trong đó bắt lỗi này là lựa chọn tốt nhất cho bạn: nó cho phép ứng dụng của bạn hoạt động, trong khi tất cả các lựa chọn thay thế khác thì không, và đó là điều cuối cùng. Tất cả "thực tiễn tốt nhất" chỉ đơn giản là tổng kết kinh nghiệm lâu dài với nhiều trường hợp thường có thể được sử dụng thay cho phân tích chi tiết về một trường hợp cụ thể để tiết kiệm thời gian; trong trường hợp của bạn, bạn đã thực hiện phân tích cụ thể và nhận được một kết quả khác. Xin chúc mừng, bạn có khả năng suy nghĩ độc lập!

. rất có thể ở trạng thái không được coi là có thể, giống như việc phân bổ đã thất bại. Nhưng điều đó không có nghĩa là giải pháp của bạn vẫn không thể là giải pháp tốt nhất.)


3
Cảm ơn. Những nghi ngờ của tôi đã phần nào được củng cố sau khi tôi phát hiện ra rằng .NET đã tạo ra StackOverflowExceptionmột ngoại lệ không thể bắt được. Tôi biết, đó là một nền tảng khác, nhưng tôi nghĩ họ có thể có lý do. Ngoài ra, quan điểm của bạn liên quan đến khởi tạo đối tượng là tại chỗ. Điều này khiến tôi nghĩ rằng tôi nên bắt SOE này một vài lớp trừu tượng bên dưới, để tôi không bắt SOE "sai".
Ionuț G. Stan

14
+1: thực tiễn tốt nhất phải luôn đi kèm với giải thích tại sao và trong bối cảnh nào chúng là "tốt nhất", để bạn có thể đánh giá liệu chúng có áp dụng cho trường hợp cụ thể của bạn hay không.
Michael Borgwardt

situations herenên situations where.
Phục vụ

2

Tôi không biết có bất kỳ rủi ro cụ thể nào về JVM ở đây không, nhưng nhìn chung nó có vẻ khá hợp lý.

Ví dụ, có các thuật toán đệ quy, như quicksort ngây thơ, có log(n)độ sâu ngăn xếp trong trường hợp điển hình, nhưng trong trường hợp xấu nhất, chúng giảm xuống độ sâu ncó thể làm nổ tung stack.

Trường hợp xấu nhất là rất hiếm và không thể xảy ra lần nữa nếu bạn khởi động lại sắp xếp trên tập đã được sắp xếp một phần, do đó, rất có ý nghĩa để bắt ngoại lệ ngăn xếp khi xảy ra và khởi động lại công việc thay vì cố gắng ngăn lỗi xảy ra hoặc giết toàn bộ ứng dụng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.