我有一个非常简单的RMI客户端/服务器应用程序,它在不同版本的JDK(直到JDK8)上都可以正常运行。突然之间,在更新为JDK9或JDK10之后,它不再起作用。 JKD9和JDK10中必须有一些更改,可能与我无法找到的codebase属性有关。 代码和类路径,代码库,java.policy均无变化。没有。仅升级到JDK10会导致服务器崩溃。
该错误是代码库不正确时的典型错误。
java.rmi.UnmarshallException:错误解组参数 java.lang.ClassNotFoundException。
这是代码,非常非常愚蠢。 我们有一个远程接口IServer.java
package sd.rmi.server;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface IServer extends Remote {
String sayHello() throws RemoteException;
}
然后,我们有了实现远程接口的类。
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();
}
}
}
项目结构很简单。有一个基于exampleirRMI的目录。然后,对于java类,我们有exampleRMI \ src。然后为字节码提供exampleRMI \ bin,为java.policy提供exampleRMI \ security,策略为
grant {
permission java.security.AllPermission;
};
然后我们有一个ant build.xml文件:
<?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>
然后我们启动rmiregistry
rmiregistry -J-Djava.rmi.server.useCodebaseOnly=false
以及使用的小型应用程序
ant build server
非常欢迎任何帮助。