1

我可以在jvm. 我的意思是我可以将关闭从我的 JVM 附加到以不同方式运行的 weblogic 服务器jvm吗?

4

2 回答 2

2

关闭挂钩部分在Runtime

跨 JVM部分您必须自己实现,因为只有您知道 JVM 如何发现和识别自己。

它可以像在 JVM1 启动时创建一个侦听套接字一样简单,并将 JVM2 的端口号发送给它。JVM1 会在其关闭挂钩中向 JVM2(发送到该端口)发送关闭通知。

于 2014-01-16T06:25:45.257 回答
2

简短的回答是:您可以,但不是开箱即用,并且存在一些陷阱,因此请阅读最后的陷阱部分。

关闭挂钩必须是jvm 可以访问的线程对象Runtime.addShutdownHook(Thread) 。因此,它必须在该 jvm 中实例化。

我看到的唯一方法是实现一个Runnablethat isSerializable和某种远程服务(例如 RMI),你可以通过SerializableRunnable. 然后,该服务必须创建一个Thread传递SerializableRunnable给该Thread构造函数并将其作为关闭挂钩添加到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类并将其实例传递给远程服务。您总是必须将它添加到远程 JVM 类路径中。

所以这种方法只有在RemoteRunnable实现了一个可以由RemoteRunnable.

如果您想动态地将任意关闭挂钩代码添加到远程 JVM,而无需修改远程 JVM 类路径,您必须使用动态语言并将该脚本传递给远程服务,例如 groovy。

于 2014-01-16T06:29:34.003 回答