2012-06-13 27 views
17

Tôi nghe nói rằng bắt được java.lang.Error được coi là thực hành không tốt. Tôi hiện đang tải một tệp .dll không được bảo đảm trên PATH và muốn chuyển sang vị trí do người dùng định cấu hình trong trường hợp không phải.Bắt lỗi Java

try { 
    System.loadLibrary("HelloWorld"); 
} catch(UnsatisfiedLinkError ule){ 
    System.load("C:/libraries/HelloWorld.dll"); 
} 

Có cách nào tốt hơn để làm việc này không? Hoặc đang bắt các UnsatisfiedLinkError ở đây có thể chấp nhận được không?

+5

Không có ý tưởng về sự thích hợp ở đây, nhưng bạn có thể kiểm tra xem tệp tồn tại trước khi thử ... ['tệp mới (" path/helloworld.dll ") .exists()'] (http: // docs. oracle.com/javase/7/docs/api/java/io/File.html#exists%28%29) .... (chỉnh sửa: đề nghị sai, tôi đọc sai mã) –

+5

Tôi sẽ coi đó là giải pháp có thể chấp nhận được. –

+0

@Slanec Bạn sẽ phải tìm kiếm tất cả các thư mục trong 'java.library.path' –

Trả lời

16

Ngoài việc đưa ra lời khuyên về cách khắc phục sự cố kỹ thuật, tôi muốn dành một chút thời gian và giải thích lý do tại sao nó được coi là "thực hành không tốt" ngay từ đầu.

Hãy bắt đầu bằng cách làm rõ lớp học Error là gì.


Trong java, lỗi và ngoại lệ (là loại chính) được ném. Việc ném một trong các điều trên được thực hiện bằng cách sử dụng từ khóa throw. Mỗi lớp mở rộng java.lang.Throwable cơ bản có thể được ném.

Có hai lớp kế thừa từ lớp cơ bản Throwable: ExceptionError. Sự khác biệt giữa hai được giải thích trong tài liệu của họ:

Một Lỗi là một lớp con của Throwable rằng chỉ vấn đề nghiêm trọng mà một ứng dụng hợp lý không nên cố gắng nắm bắt. Hầu hết các lỗi là những điều kiện bất thường. [...]

Source

Lớp Exception và lớp con của nó là một hình thức Throwable rằng chỉ ra điều kiện mà một ứng dụng hợp lý có thể muốn để bắt .

Source


Như đã giải thích ở trên, lỗi và ngoại lệ được tách ra vì nguồn gốc khác nhau của họ. An Error thường chỉ ra sự cố, trong đó ứng dụng không thể khôi phục từ. Vì vậy, họ không nên bị bắt.

Điều tương tự cũng đúng với số RuntimeException, nhưng nó được sử dụng để chỉ ra sự cố với lớp ở mức cao (ví dụ: phương pháp). Trong khi đó, Error cho biết sự cố ở mức độ thấp (ví dụ: thời gian chạy).


Vì vậy, bây giờ mà bạn hiểu rằng bạn sẽ chỉ bắt ngoại lệ và các lỗi mà bạn có thể phục hồi từ, câu trả lời cho câu hỏi của bạn phải rõ ràng.

Có, nó là hoàn toàn hợp lý để nắm bắt các UnsatisfiedLinkError, bởi vì ứng dụng của bạn có thể phục hồi từ nó.


Tôi đã trình bày ở trên (chi tiết hơn và ví dụ) và một số thông tin mở rộng trong một số article on my Blog.

+0

Một lần tôi phải vi phạm mô hình này là khi tôi phải ném một lỗi bình thường thông qua một lớp học mà tôi đã phát sinh từ điều đó đã không chỉ định bất kỳ ngoại lệ nào. Vì vậy, tôi bắt nguồn từ 'RuntimeException' để kludge xung quanh yêu cầu ngôn ngữ. Vẫn muốn có một cách tốt hơn để làm điều này. – djechlin

+0

Nếu ứng dụng không thể phục hồi từ một lỗi, bạn không phải là tồi tệ hơn bắt nó, phải không? – simon

+0

@simon nếu bạn thực sự không thể phục hồi từ lỗi, bạn sẽ làm gì khi bạn bắt được nó? Nếu ứng dụng không hoạt động nữa, tại sao nó tiếp tục chạy? –

0

loadLibrary calls findLibrary() sẽ hữu ích nhưng được bảo vệ, đặt cược tốt nhất của bạn là viết ClassLoader mở rộng lớp của riêng bạn. Trình nạp lớp có một phương thức được bảo vệ có tên là findLibrary() sẽ trả về đường dẫn đến một thư viện hoặc null nếu nó không tồn tại. Bằng cách đó bạn chỉ có thể kiểm tra null thay vì bắt lỗi. Tôi không chắc chắn nếu điều này thực sự là "tốt hơn" nhưng nó sẽ loại bỏ nhu cầu của bạn để thử bắt;

+0

Thư viện có thể bị xóa sau khi kiểm tra và trước khi tải, do đó, việc thử bắt vẫn có thể cần thiết. –

0

Nếu bạn đang mã hóa phòng thủ và có thể khôi phục từ một vấn đề, thì đó không phải là Java Error. Nếu một vấn đề như vậy không phải là rất có thể, sau đó tạo một phân lớp của Exception và ném và nắm bắt điều đó. Nếu một vấn đề như vậy có khả năng xảy ra, thì nó thậm chí không nên ném một số Exception; nhưng, phải là một phần của luồng mã thông thường.

try { 
    if (config.hasCustomDLL()) { 
    System.load(config.getCustomDLL()); 
    } else { 
    System.loadLibrary(Config.DEFAULT_DLL); 
    } 
} catch (UnstatisfiedLinkError e) { 
    System.out.println("Error loading DLL: " + e); 
} 

Errors có nghĩa là cho thất bại thực sự tồi tệ, không thể phục hồi "thất bại" mà thực sự không phải là thất bại ngay cả nếu có một cách giải quyết phù hợp. Đừng quá tải hệ thống được thiết kế để xử lý sự thất bại với những gì có khả năng cấu hình hệ thống theo nhiều cách.

0

Bạn chỉ nên bắt lỗi trong các trường hợp rất cụ thể. Chỉ bắt và lỗi nếu bạn đã khám phá tất cả các khả năng khác. Tôi hoàn toàn đồng ý với mọi thứ Lukas Knuth nói. Nhưng tôi có một bổ sung nhỏ. Trong trường hợp bạn bắt gặp bất kỳ loại lỗi nào, hãy đảm bảo rằng bạn gặp lỗi từ phạm vi hẹp như bạn có thể. Ngoài ra, nếu có thể, hãy chắc chắn rằng các phương pháp bạn bắt gặp lỗi được khai báo là cuối cùng. Lý do là bắt lỗi thường có thể dẫn đến một số chương trình rất run rẩy. Hãy xem xét rằng bạn bắt gặp một lỗi trên một phương thức mà sau này được mở rộng để gọi các phương thức khác, tất cả các phương thức cơ bản này giờ đây cũng sẽ có các lỗi bị bắt (vô ý) bởi việc đánh bắt quá mức.

Nếu bạn cần bắt lỗi, hãy làm điều đó trong một khoảng thời gian hẹp, được kiểm soát.