-2

I have a problem with JAVA RMI.

I have a java ee application running, which uses rmi to call specific methods, which have to be implemented specificly for each customer. The vendor gave me an example RMI interface implementation to show how to get a specific hostinterface running. The original codefragment looked like posted example1. The Interface is running but every 2 to 3 days it stops working, without any known reason. The interfaces' log looks like it would be still running. The glassfish server, which calls the interface, shows log entries like this:

[#|2015-10-01T16:27:53.446+0200|SEVERE|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=106;_ThreadName=Thread-2;|egatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) ...

The application error log shows entries like this:

2015-10-05 08:44:07,819 [http-thread-pool-8080(4)] ERROR medexter.arden.server.engine.DelegatingHostInterface - The method evaluateRead on remote interface does not work correctly. java.rmi.NoSuchObjectException: no such object in table at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Unknown Source) ...

I found several threads like this one: java.rmi.NoSuchObjectException: no such object in table

which tells me the garbage-collection could be responsible and the registry has to be kept statically to prevent the GC from destroying the object. Meanwhile I tried out diffrent ways. My last one (which somehow shows my desparation - restarting the interface every 24h should not be the golden solution) is posted in example2. At the moment I generate an executable jar file and start it as an application. I wanted to get it running as a service later on, but first it should work without any mistakes.

Does anybody hava an idea, what the reason for the described behaviour could be? Any imporovement of the given code apprechiated. I just want to get this stuff working, without loosing connection every few days.

Thank you very much, Martin

Example 1:

import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;


public class SampleRMIProvider {

  private static RmiRegistryThread thr;

  public static void main(String[] args) {
    SampleRMIProvider prv = new SampleRMIProvider();
    prv.init();
  }

  public void init(){
    SampleRMIProvider.thr = new RmiRegistryThread();
    thr.start();
  }

  public class RmiRegistryThread extends Thread {

    public boolean run = true;

    @Override
    public void run() {
      System.err.println("thread start");
      String name = "RMIHostInterface";
      int servicePorti = Integer.parseInt("18989");
      try {
        RmiHostInterface engine = new RmiHostInterfaceImpl();
        RmiHostInterface stub = (RmiHostInterface) UnicastRemoteObject.exportObject(engine, 0);
        Registry registry;
        try {
          registry = LocateRegistry.createRegistry(servicePorti);
        } catch (RemoteException e) {
          registry = LocateRegistry.getRegistry(servicePorti);
        }
        registry.bind(name, stub);
      } catch (RemoteException e) {
        e.printStackTrace();
      } catch (AlreadyBoundException e) {
        e.printStackTrace();
      }
      try {
        while (this.run) {
          Thread.sleep(10000);
        }     
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }
}

Example 2:

import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;


public class SampleRMIProvider extends Thread{

    private static Registry r = null;

    @Override
    public void run() {
        String name = "RMIHostInterface";
        int servicePorti = Integer.parseInt("20002"); //18989

        try {
            RmiHostInterface engine = new SampleInterfaceImpl();
            RmiHostInterface stub = (RmiHostInterface) UnicastRemoteObject.exportObject(engine, 0);

            try {
                SampleRMIProvider.r = LocateRegistry.createRegistry(servicePorti);
            } catch (RemoteException e) {
                SampleRMIProvider.r = LocateRegistry.getRegistry(servicePorti);
            }
            SampleRMIProvider.r.bind(name, stub);
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (AlreadyBoundException e) {
            e.printStackTrace();
        } 
        System.err.println("RMI Interface created...");
        try{
            while(true){
                Thread.sleep(10000);
            }
        }
        catch (InterruptedException e) {
             e.printStackTrace();
        }
    }

    public static void main(String[] args) {

        try {
            while (true) {
                //RMI Interface instanzieren
                SampleRMIProvider provider = new SampleRMIProvider();
                provider.start();
                //Ein Tag pause
                Thread.sleep(86400000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

14.10.2015 Finally - this minimal example shows a solution that worked for me. Thanks for the useful advices.

import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

public class SampleRMIProvider{

private static Registry r = null;
private static SampleHostInterfaceImpl hif = null;
private static RmiHostInterface stub = null;

SampleRMIProvider(){
    try{
        SampleRMIProvider.r.bind("RMIHostInterface", SampleRMIProvider.stub);
    }
    catch(RemoteException | AlreadyBoundException e){
        e.printStackTrace();
    }
}

public static void main(String[] args) {

    //setup static references to prevent from beeing collected by GC
    try {
        SampleRMIProvider.hif = new SampleHostInterfaceImpl();  
        SampleRMIProvider.stub = (RmiHostInterface) UnicastRemoteObject.exportObject(SampleRMIProvider.hif, 0);
        try {
            SampleRMIProvider.r = LocateRegistry.createRegistry(20002);
        } catch (RemoteException e) {
            SampleRMIProvider.r = LocateRegistry.getRegistry(20002);
        }

    } catch (RemoteException e) {
        e.printStackTrace();
    }
    new SampleRMIProvider();
}
}
Community
  • 1
  • 1
MST
  • 41
  • 4

1 Answers1

0
  • I don't know what you mean by 'no known cause', when the cause is documented in the Javadoc of the exception.

  • You say that you've read that the Registry reference must be static, yet you don't have a static Registry reference anywhere.

Try implementing that.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Thanks for the clear words. With "no known cause" I tried to express, that I thought from the GC's point of view a static reference initialized inside of a referenced object (example 2) should have the same effect as a static reference set by the main method. That's why I thought I actually would have a static reference, as claimed and there should nothing be GCed at all. It seems like I don't profoundly understand GC principles. I retyped the code and initialized static Registry and Interface references with appropriate objects by the main() method. Hopefully this approach will do it. – MST Oct 10 '15 at 08:53
  • 1
    It isn't clear whether your new code works or whether you are now asking a new question, or another version of the same question. NB You don't need to keep the thread running, or the `main()` method either. If you still have a problem, you could try a static reference to `SampleProvider` ... – user207421 Oct 10 '15 at 09:25