这是我第一次使用RMI,这是我写的主要内容:

public class Main {
    public static void main(String[] args)
    {
        try {
            String name = "Server";
            ServerInterface server = new ServerRMI(0,new Executor());
            ServerInterface stub =
                    (ServerInterface) UnicastRemoteObject.exportObject(server, 0);
            Registry registry = LocateRegistry.getRegistry();
            registry.rebind(name, stub);
            System.out.println("ServerRMI bound");
        } catch (Exception e) {
            System.err.println("ServerRMI exception:");
            e.printStackTrace();
        }
    }
}


我已经阅读了this文章,建议您修改代码库,因此我将Intellij的VM选项设置为:
-Djava.rmi.server.codebase=file:/home/luca/Documents/PAD/RaftFS/target/
目标包含RaftFS-1.0-SNAPSHOT.jar,这是Maven生产的jar(因此包含ServerInterface)。显然,在午餐之前,我在外壳上执行Main程序。我的系统环境中未设置rmiregistry变量。

无论如何,这些异常在我执行此程序时引发:

/usr/lib/jvm/java-1.7.0-openjdk-amd64/bin/java -Djava.rmi.server.codebase=file:/home/luca/Documents/PAD/RaftFS/target/ -Didea.launcher.port=7535 -Didea.launcher.bin.path=/home/luca/idea-IU-139.1117.1/bin -Dfile.encoding=UTF-8 -classpath /usr/lib/jvm/java-1.7.0-openjdk-amd64/jre/lib/compilefontconfig.jar:/usr/lib/jvm/java-1.7.0-openjdk-amd64/jre/lib/rt.jar:/usr/lib/jvm/java-1.7.0-openjdk-amd64/jre/lib/charsets.jar:/usr/lib/jvm/java-1.7.0-openjdk-amd64/jre/lib/rhino.jar:/usr/lib/jvm/java-1.7.0-openjdk-amd64/jre/lib/jsse.jar:/usr/lib/jvm/java-1.7.0-openjdk-amd64/jre/lib/jce.jar:/usr/lib/jvm/java-1.7.0-openjdk-amd64/jre/lib/resources.jar:/usr/lib/jvm/java-1.7.0-openjdk-amd64/jre/lib/management-agent.jar:/usr/lib/jvm/java-1.7.0-openjdk-amd64/jre/lib/javazic.jar:/usr/lib/jvm/java-1.7.0-openjdk-amd64/jre/lib/ext/sunjce_provider.jar:/usr/lib/jvm/java-1.7.0-openjdk-amd64/jre/lib/ext/dnsns.jar:/usr/lib/jvm/java-1.7.0-openjdk-amd64/jre/lib/ext/icedtea-sound.jar:/usr/lib/jvm/java-1.7.0-openjdk-amd64/jre/lib/ext/sunpkcs11.jar:/usr/lib/jvm/java-1.7.0-openjdk-amd64/jre/lib/ext/java-atk-wrapper.jar:/usr/lib/jvm/java-1.7.0-openjdk-amd64/jre/lib/ext/zipfs.jar:/usr/lib/jvm/java-1.7.0-openjdk-amd64/jre/lib/ext/localedata.jar:/home/luca/Documents/PAD/RaftFS/out/production/main:/home/luca/idea-IU-139.1117.1/lib/idea_rt.jar com.intellij.rt.execution.application.AppMain PAD.RaftFS.Server.Main
ServerRMI exception:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
    java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
    java.lang.ClassNotFoundException: PAD.RaftFS.Server.ServerInterface
    at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:419)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:267)
    at sun.rmi.transport.Transport$2.run(Transport.java:202)
    at sun.rmi.transport.Transport$2.run(Transport.java:199)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:198)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:567)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:828)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.access$400(TCPTransport.java:619)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$1.run(TCPTransport.java:684)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$1.run(TCPTransport.java:681)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:681)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)
    at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:275)
    at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:252)
    at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:378)
    at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source)
    at PAD.RaftFS.Server.Main.main(Main.java:20)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
    java.lang.ClassNotFoundException: PAD.RaftFS.Server.ServerInterface
    at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
    at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:409)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:267)
    at sun.rmi.transport.Transport$2.run(Transport.java:202)
    at sun.rmi.transport.Transport$2.run(Transport.java:199)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:198)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:567)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:828)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.access$400(TCPTransport.java:619)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$1.run(TCPTransport.java:684)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$1.run(TCPTransport.java:681)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:681)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: PAD.RaftFS.Server.ServerInterface
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.rmi.server.LoaderHandler$Loader.loadClass(LoaderHandler.java:1206)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:274)
    at sun.rmi.server.LoaderHandler.loadClassForName(LoaderHandler.java:1219)
    at sun.rmi.server.LoaderHandler.loadProxyInterfaces(LoaderHandler.java:729)
    at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:673)
    at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:610)
    at java.rmi.server.RMIClassLoader$2.loadProxyClass(RMIClassLoader.java:646)
    at java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.java:311)
    at sun.rmi.server.MarshalInputStream.resolveProxyClass(MarshalInputStream.java:255)
    at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1558)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1514)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
    ... 17 more


重要更新:如果将CLASSHPATH替换为Registry registry = LocateRegistry.getRegistry();并避免执行Registry registry = LocateRegistry.createRegistry(1099);,则不会引发异常。我可以假设使用rmiregistry参数将该寄存器绑定到一个匿名端口吗?为什么会这样?它实际上解决了问题吗?

最佳答案

为了回答您的实际问题,注册表在其CLASSPATH上没有提到的类。使用代码库功能是解决此问题的一种方法,但是它很复杂。一个更简单的解决方案是使用LocateRegistry.createRegistry().在服务器JVM中启动注册表。

您可以为此使用端口零,这确实表示一个匿名端口,但是这样做完全没有意义。它与原始问题没有关系,只会使您的注册表无法为客户找到。

另一种解决方案是在启动注册表时指定CLASSPATH,具体方法如下:

rmiregistry -J-classpath=...

10-07 19:39