1

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?

chiru
  • 812
  • 5
  • 17
  • 32

2 Answers2

2

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.

Oleg Mikheev
  • 17,186
  • 14
  • 73
  • 95
2

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.

René Link
  • 48,224
  • 13
  • 108
  • 140
  • great design, but some people recommend avoiding serialization at all costs – Oleg Mikheev Jan 16 '14 at 06:39
  • @OlegMikheev Do you know why they recommend that? – René Link Jan 16 '14 at 06:43
  • with serialization you restrict yourself to exactly the same JVM version across all parties, and there are [so many things to keep in mind bout serialization](http://www.javajee.com/best-practices-for-serialization-in-java) that the "best practise is not to use it" (citing Bob Lee) – Oleg Mikheev Jan 16 '14 at 06:52
  • @OlegMikheev serialization does not restrict you to the same jvm version accross all parties. Otherwise exceptions accross different JVMs would not work (they are serializable). Of course the class that you pass through different JVMs must be binary compatible with the classes in that JVM. That's why you have to take care about the class's version that is deployed in different JVMs. – René Link Jan 16 '14 at 07:02
  • That's true in theory, but in real life [this kind of problems](http://stackoverflow.com/questions/13599217/how-to-get-rid-of-invalidclassexception-serialversionuid) happen periodically. In times of Java 1.3 serialization issues were a disaster, lately these problems are less common, maybe because nobody is using it? :) – Oleg Mikheev Jan 16 '14 at 07:51
  • @OlegMikheev I agree that the java.io.InvalidClassException occurs often, but I think that it occurs because pages like http://wiki.eclipse.org/Evolving_Java-based_APIs_2 are not read very close. :) – René Link Jan 16 '14 at 07:57