chiru
chiru

Reputation: 832

Java shutdown hook across different JVM

Can i attach java shutdown hook across jvm . I mean can I attach shut down from my JVM to weblogic server running in different jvm?

Upvotes: 1

Views: 879

Answers (2)

René Link
René Link

Reputation: 51403

The short anser is: You can, but not out of the box and there are some pitfalls so please read the section pitfalls at the end.

A shutdown hook must be a thread object Runtime.addShutdownHook(Thread) that the jvm can access. Thus it must be instantiated within that jvm.

The only way I see to do it is to implement a Runnable that is also Serializable and some kind of remote service (e.g. RMI) which you can pass the SerializableRunnable. This service must then create a Thread pass the SerializableRunnable to that Thread's constructor and add it as a shutdown hook to the Runtime.

But there is also another problem in this case. The SerializableRunnable has no references to objects within the remote service's jvm and you have to find a way how that SerializableRunnable can obtain them or to get them injected. So you have the choice between a ServiceLocator or an dependency injection mechanism. I will use the service locator pattern for the following examples.

I would suggest to define an interface like this:

 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);
 }

The remote service method could then look like this

 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));
    }

 }

and your RemoteRunnable might look lioke this

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);
    }

 }

Pitfalls

There is only one problem with this approach that is not obvious. The RemoteRunnable implementation class must be available in the remote service's classpath. Thus you can not just create a new RemoteRunnable class and pass an instance of it to the remote service. You always have to add it to the remote JVMs classpath.

So this approach only makes sense if the RemoteRunnable implements an algorithm that can be configured by the state of the RemoteRunnable.

If you want to dynamically add arbitrary shutdown hook code to the remote JVM without the need to modify the remote JVMs classpath you must use a dynamic language and pass that script to the remote service, e.g. groovy.

Upvotes: 2

Oleg Mikheev
Oleg Mikheev

Reputation: 17444

The shutdown hook part is in Runtime.

The across JVM part you'll have to implement yourself, because only you know how your JVMs can discover and identify themselves.

It could be as simple as creating a listening socket at JVM1 startup, and sending port number of JVM2 to it. JVM1 would send shutdown notification to JVM2 (to that port) in its shutdown hook.

Upvotes: 2

Related Questions