0

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.

ardot
  • 1
  • 2
  • 1
    Java 9 introduced a new module system. Be sure to check if you have the correct modules loaded. [According to the Java API documentation](https://docs.oracle.com/javase/9/docs/api/java.rmi-summary.html) you need to include the `java.rmi` module – Lukas Sep 20 '18 at 12:07
  • 2
    It would be interesting to know if you were using a recent or really old JDK 8 update. This is interesting because remote class loading was disabled by default a long time ago and maybe this is what you are running into. – Alan Bateman Sep 20 '18 at 15:49
  • As far as I know, we can still use the non-modular code in JDK9, and in any case, the java.rmi module belongs to java.base module. – ardot Sep 21 '18 at 14:51
  • We are using the latest update JDK 1.8.0_181. – ardot Sep 21 '18 at 15:03
  • Additional information that may help is that in order to avoid problems with the specificities of the codebase, we are setting the java.rmi.server.useCodebaseOnly property back to false. – ardot Sep 21 '18 at 15:34
  • 1
    Off hand, I can't think of anything in JDK 9 to explain what you are seeing. It may be useful to share a standalone project that shows the `rmiregistry` and other commands that you are using. It's probably something simple not right, just not enough information in the post or discussion here to guess. – Alan Bateman Sep 22 '18 at 07:05
  • Thank you very much, Alan. I added some more detail to my questions. As I said, any help is very much welcome. – ardot Sep 24 '18 at 15:03
  • What @AlanBateman wanted to suggested is to actually provide a [mcve] to allow other people to reproduce it. Otherwise, only people who stumbled upon the exact same issue already would be able to help you. – Didier L Sep 24 '18 at 15:26
  • Thanks again for your kind support. I edited the question and added the interface, class, and ant file. Hope this helps. – ardot Oct 03 '18 at 12:57
  • A note to share that Java 12 solved the problem, whatever that problem was. All my RMI applications work perfectly well now. No changess done, just upgrade to version 12 and everything is up and running. – ardot Oct 27 '19 at 19:49

0 Answers0