2010-02-26 37 views
19

Tôi hiện đang xây dựng một ứng dụng bằng Tomcat, Spring và JAVA. Tôi đang sử dụng Log4J làm thư viện đăng nhập của mình. Tôi hiện đang đăng nhập tất cả mọi thứ vào một tập tin văn bản. Một trong những vấn đề tôi gặp phải là RuntimeExceptions không được ghi vào bất kỳ tệp nào. Tôi đã tự hỏi nếu có một cách để đăng nhập tất cả RuntimeExceptions có thể ném vào tập tin đăng nhập ứng dụng của tôi. Nếu không phải là nó có thể có nó đăng nhập vào một tập tin đăng nhập? Có cách nào tiêu chuẩn để làm điều này không? Nếu có cách nào tiêu chuẩn để thực hiện điều này khi chạy ứng dụng của bạn trong Tomcat?Nhật ký thời gian chạy Ngoại lệ trong Java bằng cách sử dụng log4j

Cảm ơn bạn trước sự giúp đỡ của bạn!

+2

Bạn có nghĩa là "không xác định" ngoại lệ thời gian không? –

+0

Vâng, tôi có nghĩa là "không bị bắt buộc" RuntimeExceptions – DkS

Trả lời

21

Tôi không chắc chắn nếu đây là những gì bạn đang tìm kiếm, nhưng có một xử lý cho trường hợp ngoại lệ chấm dứt chủ đề. Nó là một trình xử lý cho bất kỳ ngoại lệ nào không bị bắt một cách rõ ràng bởi đích của luồng.

Trình xử lý ngoại lệ chưa xử lý mặc định chỉ cần gọi printStackTrace() trên Throwable để in dấu vết ngăn xếp thành System.err. Tuy nhiên, bạn có thể replace này với riêng UncaughtExceptionHandler bạn mà ghi lại ngoại lệ cho Log4j thay vì:

class Log4jBackstop implements Thread.UncaughtExceptionHandler { 

    private static Logger log = Logger.getLogger(Log4jBackstop.class); 

    public void uncaughtException(Thread t, Throwable ex) { 
    log.error("Uncaught exception in thread: " + t.getName(), ex); 
    } 

} 

Nếu bạn đang sử dụng một khuôn khổ thi hành di chúc mà bạn vượt qua một đối tượng Runnable, chủ đề của nó có thể có catch khối riêng của họ mà ngăn chặn ngoại lệ từ việc đạt được trình xử lý ngoại lệ chưa được nắm bắt. Nếu bạn muốn nắm bắt Runtime trường hợp ngoại lệ ở đó, một cách để thực hiện việc này là bao bọc từng tác vụ trong trình bao bọc nhật ký, như sau:

class Log4jWrapper { 

    private final Logger log; 

    private final Runnable target; 

    Log4jWrapper(Logger log, Runnable target) { 
    this.log = Objects.requireNonNull(log); 
    this.target = Objects.requireNonNull(target); 
    } 

    public void run() { 
    try { 
     target.run(); 
    } catch(RuntimeException ex) { 
     log.error("Uncaught exception.", ex); 
     throw ex; 
    } 
    } 

} 

... 

Runnable realTask = ...; 
executor.submit(new Log4jWrapper(Logger.getLogger(Whatever.class), realTask)); 
+0

Đây có phải là cách mà các RuntimeExceptions này được xử lý trong các ứng dụng không? Tôi đoán tôi tự hỏi nếu đây là một cách tiêu chuẩn để đối phó với điều này. – DkS

+0

Ngoài ra tôi đang sử dụng ThreadPoolTaskExecutor từ Spring API, đây có phải là thứ gì đó có thể được thực hiện bằng cách sử dụng lớp này không? – DkS

+0

Điều này làm việc tuyệt vời nếu có một RuntimeException trên Runnable, tuy nhiên những gì nếu có một ngoại lệ với ThreadPoolTaskExecutor? Nói nó ném một RunTimeException bởi vì các hồ bơi đã được cấu hình trong chính xác .... điều này sẽ vẫn in cho giao diện điều khiển và không được đăng nhập .... bất cứ đề nghị? – DkS

1

Bạn có thể thử chuyển hướng StdErr để sử dụng trình ghi nhật ký của mình. Điều này sẽ xuất kết quả của bất cứ điều gì được ghi vào lỗi std của bạn (bao gồm các ngoại lệ chưa được xử lý)

Bài đăng trên blog này cung cấp một tóm tắt tốt về cách thực hiện chuyển hướng vào FileHandler ngoài bộ ghi nhật ký của bạn.

https://blogs.oracle.com/nickstephen/entry/java_redirecting_system_out_and

12

Một cách để đăng nhập RuntimeExceptions còn tự do (hoặc bất kỳ Throwables còn tự do cho rằng vấn đề) là để tạo ra một lớp mà thực hiện Thread.UncaughtExceptionHandler. Phương thức uncaughtException() của lớp này sẽ chỉ viết chi tiết ngoại lệ vào nhật ký. Bạn có thể làm cho JVM gọi trình xử lý ngoại lệ này bất cứ khi nào một RuntimeException vô tình chấm dứt một chuỗi bằng cách thêm dòng

Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler()); 

vào mã của bạn.

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