簡體   English   中英

跨不同JVM的Java關閉掛鈎

[英]Java shutdown hook across different JVM

我可以在jvm附加java shutdown鈎子嗎? 我的意思是我可以將關閉的JVM連接到運行在不同jvm weblogic服務器嗎?

關機鈎子部分在運行時中

跨JVM部分,您將必須實現自己,因為只有您知道JVM如何發現和識別自己。

就像在JVM1啟動時創建偵聽套接字,然后向其發送JVM2的端口號一樣簡單。 JVM1將在其關閉掛鈎中向JVM2發送關閉通知(至該端口)。

簡短的答案是:您可以,但不能開箱即用,並且有一些陷阱,因此請閱讀最后的陷阱部分。

關閉鈎子必須是jvm可以訪問的線程對象Runtime.addShutdownHook(Thread) 因此,必須在該jvm中實例化它。

我看到的唯一方法是實現一個可SerializableRunnable以及可以傳遞SerializableRunnable某種遠程服務(例如RMI)。 然后,此服務必須創建一個Thread通過SerializableRunnableThread的構造函數,並將其添加為關閉掛鈎的Runtime

但是在這種情況下還有另一個問題。 SerializableRunnable沒有對遠程服務的jvm中的對象的引用,您必須找到一種方式SerializableRunnable可以獲取它們或將其注入。 因此,您可以在ServiceLocator依賴項注入機制之間進行選擇。 我將在以下示例中使用服務定位器模式。

我建議定義一個這樣的接口:

 public interface RemoteRunnable extends Runnable, Serializable {

       /**
         * Called after de-serialization from a remote invocation to give the
         * RemoteRunnable a chance to obtain service references of the jvm it has
         * been de-serialized in.
         */
      public void initialize(ServiceLocator sl);
 }

遠程服務方法可能如下所示

 public class RemoteShutdownHookService {

    public void addShutdownhook(RemoteRunnable rr){
        // Since an instance of a RemoteShutdownHookService is an object of the remote
        // jvm, it can provide a mechanism that gives access to objects in that jvm.

        // Either through a service locator
        ServiceLocator sl = ...;
        rr.initialize(sl);

        // or a dependency injection. 
        // In case of a dependecy injection the initialize method of RemoteRunnable
        // can be omitted.
        // A short spring example:
        //
        // AutowireCapableBeanFactory beanFactory = .....;
        // beanFactory.autowireBean(rr);

        Runtime.getRuntime().addShutdownHook(new Thread(rr));
    }

 }

和您的RemoteRunnable可能看起來像這樣

public class SomeRemoteRunnable implements RemoteRunnable {

    private static final long serialVersionUID = 1L;
    private SomeServiceInterface someService;

    @Override
    public void run() {
        // call someService on shutdown
        someService.doSomething();
    }

    @Override
    public void initialize(ServiceLocator sl) {
        someService = sl.getService(SomeServiceInterface.class);
    }

 }

陷阱

這種方法只有一個不明顯的問題。 RemoteRunnable實現類必須在遠程服務的類路徑中可用。 因此,您不能只創建一個新的RemoteRunnable類並將其實例傳遞給遠程服務。 您始終必須將其添加到遠程JVMs類路徑。

因此,僅當RemoteRunnable實現可由RemoteRunnable狀態配置的算法時,此方法才有意義。

如果要向遠程JVM動態添加任意關閉掛鈎代碼而無需修改遠程JVM類路徑,則必須使用動態語言並將該腳本傳遞給遠程服務,例如groovy。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM