繁体   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