2012-12-11 16 views
6

Tôi có một lớp logger chuyên dụng sử dụng lớp java.util.logging.Logger. Tôi muốn có thể sử dụng logger này trong hook shutdown của class khác. Tuy nhiên, có vẻ như không đăng nhập lúc tắt máy. Từ những gì tôi đọc, có thể đã có một cái móc tắt máy được kích hoạt cho chính bản ghi nhật ký đang gây ra vấn đề.Java -Làm thế nào để có được logger để làm việc trong móc tắt máy?

Làm cách nào để làm việc này? Lý tưởng nhất, tôi muốn nó được nhìn thấy trong tập tin đăng nhập mà tôi đã làm trong thực tế thực hiện móc tắt máy khi quá trình chấm dứt.

+0

Tôi không chắc liệu điều này có đúng hay không nhưng bạn không có quyền kiểm soát thứ tự mà các móc tắt máy xảy ra. –

+1

Đúng, chúng chạy [đồng thời] (http://docs.oracle.com/javase/1.5.0/docs/guide/lang/hook-design.html) –

Trả lời

8

Một lần nữa nhìn vào nguồn, giải pháp dường như là để xác định một hệ thống sở hữu java.util.logging.manager mà là một lớp con của LogManager mà override phương thức reset(); nên Loggers tiếp tục làm việc trên tắt máy.

import java.util.logging.LogManager; 
import java.util.logging.Logger; 

public class Main { 
    static { 
     // must be called before any Logger method is used. 
     System.setProperty("java.util.logging.manager", MyLogManager.class.getName()); 
    } 

    public static class MyLogManager extends LogManager { 
     static MyLogManager instance; 
     public MyLogManager() { instance = this; } 
     @Override public void reset() { /* don't reset yet. */ } 
     private void reset0() { super.reset(); } 
     public static void resetFinally() { instance.reset0(); } 
    } 

    public static void main(String... args) { 
     Logger logger1 = Logger.getLogger("Main1"); 
     logger1.info("Before shutdown"); 
     Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        Logger logger2 = Logger.getLogger("Main2"); 
        logger2.info("Shutting down 2"); 

       } finally { 
        MyLogManager.resetFinally(); 
       } 
      } 
     })); 
    } 
} 

in

Dec 11, 2012 5:56:55 PM Main main 
INFO: Before shutdown 
Dec 11, 2012 5:56:55 PM Main$1 run 
INFO: Shutting down 2 

Từ mã này cho LogManager, bạn có thể thấy thấy có một cái móc shutdown mà dismantles các trình xử lý và đóng chúng. Logger chỉ hoạt động khi tắt máy nếu nó chưa được sử dụng trước đó nên mã này không chạy.

// This private class is used as a shutdown hook. 
// It does a "reset" to close all open handlers. 
private class Cleaner extends Thread { 

    private Cleaner() { 
     /* Set context class loader to null in order to avoid 
     * keeping a strong reference to an application classloader. 
     */ 
     this.setContextClassLoader(null); 
    } 

    public void run() { 
     // This is to ensure the LogManager.<clinit> is completed 
     // before synchronized block. Otherwise deadlocks are possible. 
     LogManager mgr = manager; 

     // If the global handlers haven't been initialized yet, we 
     // don't want to initialize them just so we can close them! 
     synchronized (LogManager.this) { 
      // Note that death is imminent. 
      deathImminent = true; 
      initializedGlobalHandlers = true; 
     } 

     // Do a reset to close all active handlers. 
     reset(); 
    } 
} 


/** 
* Protected constructor. This is protected so that container applications 
* (such as J2EE containers) can subclass the object. It is non-public as 
* it is intended that there only be one LogManager object, whose value is 
* retrieved by calling Logmanager.getLogManager. 
*/ 
protected LogManager() { 
    // Add a shutdown hook to close the global handlers. 
    try { 
     Runtime.getRuntime().addShutdownHook(new Cleaner()); 
    } catch (IllegalStateException e) { 
     // If the VM is already shutting down, 
     // We do not need to register shutdownHook. 
    } 
} 

Từ thử nghiệm của riêng tôi

Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { 
    @Override 
    public void run() { 
     try { 
      Logger logger2 = Logger.getLogger("Main2"); 
      logger2.info("Shutting down 2"); 
     } catch (Throwable t) { 
      t.printStackTrace(); 
     } 
    } 
})); 

in

Dec 11, 2012 5:40:15 PM Main$1 run 
INFO: Shutting down 2 

nhưng nếu bạn thêm

Logger logger1 = Logger.getLogger("Main1"); 

bên ngoài khối này bạn nhận được gì.

+1

Ngay cả khi sử dụng 'Logger.getLogger (tên) tôi vẫn không thấy bất cứ điều gì được in vào nhật ký của mình. Tuy nhiên, thiết lập thuộc tính hệ thống và sao chép qua mã MyLogManager tôi đã có thể làm cho nó hoạt động.Đẹp, cảm ơn bạn! – Marianna

1

Móc tắt máy có lợi thế gì không?

Bạn tốt hơn, thêm đầu ra Đăng nhập dòng cuối cùng trong chính: Các khối finally sẽ được thực hiện trong mọi trường hợp, trừ khi tai nạn VM nhưng sau đó móc tắt máy sẽ không được thực hiện, quá.

static void main(String[] argv) { 

    try { 
    startApp(); 
    } finally { 
    LOGGER.info("shudown"); 
    } 
} 
+0

Quá trình của tôi là một quá trình hoạt động cả ngày - ngồi và chờ đợi điều gì đó xảy ra. Không phải là một loại và thực hiện một điều mà tôi có thể chỉ cần đặt những gì tôi cần ở phần cuối của mã. Tôi tin rằng một móc tắt là giải pháp đúng – Marianna

+1

Vì vậy, có vẻ như bạn không biết nơi kết thúc của mã của bạn là? Bạn nên biết điều đó, và tìm hiểu. Điều này không có gì để làm với một shot! Sw của chúng tôi chạy trong nhiều tuần mà không tắt máy, nhưng chúng tôi biết nơi kết thúc là. Có lẽ nó là một chút khó khăn, bằng cách sử dụng mùa xuân hoặc khuôn khổ khác. Nhưng bạn nên biết để làm sạch, bởi vì thường là một lệnh shutdoiwn là cần thiết! Lý do tại sao LOGGING cần một trình xử lý shutdown là một lib của nó và không thể knwo "end of code" – AlexWien

+0

Quá trình không tự thoát ra, do đó tương tự như vậy không có kết thúc hợp lý. – Marianna