JDK8 RMI server not working in JDK9 or JDK10 - ClassNotFoundException

1.3k Views Asked by At

I have a very simple RMI client/server application that has been working perfectly well on different versions of JDK, up to JDK8. All of a sudden, it does not work anymore after updating to JDK9 or JDK10. There must be some change in JKD9 and JDK10, probably related to the codebase property, that I have been unable to find. No changes neither in the code, nor in the classpath, codebase, java.policy. Nothing. Only upgrading to JDK10 and the server crashes.

The error is the typical one when the codebase is not correct.

java.rmi.UnmarshallException:error unmarshalling arguments java.lang.ClassNotFoundException.

This is the code, which is very very silly. We have a remote interface, IServer.java

package sd.rmi.server;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface IServer extends Remote {
 String sayHello() throws RemoteException;
}

Then we have the class that implements the remote interface.

package sd.rmi.server;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

public class Server implements IServer {
private static final long serialVersionUID = 1L;
protected Server() throws RemoteException {
    super();
}

public String sayHello() {
    return "Hello World!";
}

public static void main(String[] args) {

    if (System.getSecurityManager() == null) {
        System.setSecurityManager(new SecurityManager());
    }
    String name = "//" + args[0] + ":" + args[1] + "/" + args[2];
    try {       
        IServer objServer = new Server();
        IServer stubServer = (IServer) UnicastRemoteObject.exportObject(objServer,0);
        Registry registry = LocateRegistry.getRegistry();
        registry.rebind(name, stubServer);
        System.out.println("* Server '" + name + "' active and waiting...");
    } catch (Exception e) {
        System.err.println("- Exception running the server: " + e.getMessage());
        e.printStackTrace();
    }
}
}

The project structure is simple. There is basedir, named exampleRMI. Then we have exampleRMI\src for the java classes. Then exampleRMI\bin for the bytecodes, and exampleRMI\security for the java.policy and the policy is

grant {
    permission java.security.AllPermission;
};

Then we have an ANT build.xml file:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project basedir="." name="2.2_exampleRMI_Server">    
<property name="source.dir" location="src"/>
<property name="build.dir" location="bin"/>
<property name="classpath" location="bin"/>
<property name="server.port" value="1099"/> 
<property name="server.IP" value="127.0.0.1"/>
<property name="server.Name" value="HelloServer"/>
<property name="policy.file" location="security/java.policy"/>  



<target name="build" description="Builds the project">
    <delete dir="${build.dir}"/>
    <mkdir dir="${build.dir}"/>
    <javac srcdir="${source.dir}" destdir="${build.dir}" classpath="${classpath}" deprecation="true" fork="true" includeAntRuntime="no"/>
</target>

<target name="server" description="Runs the Server">
    <java classname="sd.rmi.server.Server" classpath="${classpath}" fork="true">
        <jvmarg value="-Djava.rmi.server.codebase=file:${build.dir}/"/>
        <jvmarg value="-Djava.security.policy=${policy.file}"/> 
        <jvmarg value="-Djava.rmi.server.useCodebaseOnly=false"/>           
        <arg value="${server.IP}"/> 
        <arg value="${server.port}"/> 
        <arg value="${server.Name}"/> 
    </java>
</target>

Then we launch the rmiregistry

rmiregistry -J-Djava.rmi.server.useCodebaseOnly=false

And the tiny application using

ant build server

Any help will be very much welcome.

0

There are 0 best solutions below