Java.rmi.NoSuchObjectException: Exception of such an object

The questions have already talked about this, but their answers show that the exported object was GC'd on the server side and this is causing problems. However, this does not seem to be a problem.

The specified exception is only thrown on a single machine:

PRETTY_NAME="Debian GNU/Linux 8 (jessie)"
NAME="Debian GNU/Linux"
VERSION_ID="8"
VERSION="8 (jessie)"

      

With java:

java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

      

This happens on the same machine with OpenJDK 7something.

Consistent with the other answers, I have to stick to a strong reference to object handling. I am doing this now, so what else can I do?

The same code works on both windows and another remote Linux machine with java 7. Any ideas why?

I have implemented some finalizers for related classes, but none of them get called.

As I said, I am using static links. As for me, there is no way to get the exported GC object. An exception is thrown when a remote method is called immediately after searching for an object.

Class class

public class Client{
     //some fields
    private final int RMI_PORT;
    private static SearchTestServiceImpl searchTestService;
    private static Remote stub;
    private Registry registry;
    //and starting service
    public void startService() throws RemoteException {
        createRegistry();
        searchTestService = new SearchTestServiceImpl(name);
        stub = UnicastRemoteObject.exportObject(searchTestService, RMI_PORT + 1);
        registry.rebind(SearchTestService.class.getName(), stub);
        log.info("Binding {} to port {}", SearchTestService.class.getName(), RMI_PORT + 1);
    }

    private void createRegistry() throws RemoteException {
        log.info("Starting RMI registry on port {}", RMI_PORT);
        registry = LocateRegistry.createRegistry(RMI_PORT);
        }

(...)
    }

      

And the bootstrap code

public class Bootstrap {

    private Logger log = LoggerFactory.getLogger(Bootstrap.class);
    private static Client c;

    public static void main(String[] args) throws NumberFormatException, 
// some preparations
        c = new Client(Integer.valueOf(port), name);
        c.startService();
        System.gc();
        System.runFinalization();
        synchronized (c) {
            c.wait();
        }

    }
}

      

and stacktrace

java.rmi.NoSuchObjectException: no such object in table
    at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Unknown Source) ~[na:1.7.0_65]
    at sun.rmi.transport.StreamRemoteCall.executeCall(Unknown Source) ~[na:1.7.0_65]
    at sun.rmi.server.UnicastRef.invoke(Unknown Source) ~[na:1.7.0_65]
    at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(Unknown Source) ~[na:1.7.0_65]
    at java.rmi.server.RemoteObjectInvocationHandler.invoke(Unknown Source) ~[na:1.7.0_65]
    at com.sun.proxy.$Proxy0.getName(Unknown Source) ~[na:na]
    at call to a method of remote lookedup object #getName in this example.

      

Requested Code Snippet - Search and Call Throwing Exception

//somewhere

SearchTestService c = getClient(address); // this returns nice stub
String name = c.getName(); // this is throwing exception

private SearchTestService getClient(String string) throws NumberFormatException, RemoteException, NotBoundException {
    String[] parts = string.split(":");
    Registry registry = LocateRegistry.getRegistry(parts[0], Integer.parseInt(parts[1]));
    SearchTestService client = (SearchTestService) registry.lookup(SearchTestService.class.getName());
    return (SearchTestService) client;
}

      

Console exit after starting "listening" for client code (with RMI registry)

10:17:55.915 [main] INFO  pl.breeze.searchtest.client.Client - Starting RMI registry on port 12097
10:17:55.936 [main] INFO  p.b.s.client.SearchTestServiceImpl - Test agent Breeze Dev staging is up and running
10:17:55.952 [main] INFO  pl.breeze.searchtest.client.Client - Binding pl.choina.searchtest.remote.SearchTestService to port 12098

      

And it waits until the health check completes.

+3


source to share


1 answer


NoSuchObjectException

      

Javadoc :

A NoSuchObjectException is thrown if an attempt is made to call a method on an object that no longer exists on the remote virtual machine.

This means that the remote object referenced by the stub you are calling methods has not been opened, i.e. the stub is "obsolete". The only way that can happen is not to export the object, either manually or as a result of GC.

As I said, I am using static links.

No no. The static Registry

must be done. Otherwise, you just create a loop between Client

and Registry

, which can be garbage collected right away.

Why you call your server Client

is another mystery.

EDIT Several comments:

stub = UnicastRemoteObject.exportObject(searchTestService, RMI_PORT + 1);

      

There is no need to use the second port here. Just reinstall the registry port.

log.info("Binding {} to port {}", SearchTestService.class.getName(), RMI_PORT + 1);

      



This is misleading. You've already done both, but what you did is:

  • Exports an object to a port and
  • Associate an object with a name

in two separate steps.

System.gc();
System.runFinalization();

      

Strange things to do here, or even anywhere.

synchronized (c) {
    c.wait();
}

      

This is unreliable. You don't need anything here, since RMI has to keep the JVM open as long as it exports remote objects, but you can do what the registry does:

while (true)
{
    Thread.sleep(Integer.MAX_VALUE);
}

      

with appropriate exception handling.

I cannot reproduce your problem, but then I am on Windows 7.

-1


source







All Articles