RMI 客户端无法查找服务器 - java.rmi.UnmarshalException

Posted

技术标签:

【中文标题】RMI 客户端无法查找服务器 - java.rmi.UnmarshalException【英文标题】:RMI client cannot lookup server - java.rmi.UnmarshalException 【发布时间】:2014-04-11 12:16:00 【问题描述】:

我有一个 java rmi 服务器和一个 java rmi 客户端在两台不同的机器上

服务器基本上是一个 fibonacy 计算器。它接收一堆数字并根据它们计算斐波那契数列。

客户端只需发送一堆数字供服务器计算。

FiboServer 项目由三个类组成:

IFibonacci.java:一个接口 Fibonacci.java:实现之前定义的接口 FibonacciServer.java:有主服务器,运行服务器

FibonacciServer.java:

package fiboserver;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class FibonacciServer 
    public static void main(String args[])

        if (System.getSecurityManager() == null) 
            System.setProperty("java.security.policy", "server.policy");
            System.setSecurityManager(new SecurityManager());
        

        try
            IFibonacci fib = new Fibonacci();

            // Bind the remote object's stub in the registry
            Registry registry = LocateRegistry.createRegistry(1099);
            registry.rebind("fibonacci", fib);

            System.out.println("Fibonacci Server ready.");
        catch(RemoteException rex)
            System.err.println("Exception in Fibonacci.main " + rex);
        
    

客户端项目只有一个类:FibonacciClient.java。

FibonacciClient.java:

package fiboclient;

import fiboserver.IFibonacci;
import java.math.BigInteger;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class FibonacciClient 

    public static void main(String[] args) 

        if (System.getSecurityManager() == null) 
            System.setProperty("java.security.policy", "client.policy");
            System.setSecurityManager(new SecurityManager());
        

        try
            //args[0] = server Public IP
            Registry registry = LocateRegistry.getRegistry(args[0]);
            IFibonacci calculator = (IFibonacci) registry.lookup("fibonacci");

            //the rest of the args are just numbers to calculate
            for(int i = 1; i < args.length; i++)
                try
                    BigInteger index = new BigInteger(args[i]);
                    BigInteger f = calculator.getFibonacci(index);

                    System.out.println("The " + args[i] + "th Fibonacci number "
                            + "is " + f);
                catch(NumberFormatException e)
                    System.err.println(args[i] + " is not an integer.");
                
            
        catch(RemoteException e)
            System.err.println("Remote object threw exception " + e);
         catch (NotBoundException e) 
            System.err.println("Could not find the requested remote object on "
                    + "the server: " + e);
        
    


两个项目都有一个策略文件,服务器有一个server.policy,客户端有一个client.policy 文件。两个文件的内容相同:

grant
    permission java.security.AllPermission;
;

我正在使用 java -jar FiboServer.jar -Djava.net.preferIPv4Stack=true -Djava.rmi.server.hostname=12.34.56.789 在服务器机器中启动 FiboServer

我正在使用java -jar FiboClient.jar 12.34.56.789 1 2 3 4 5 启动客户端。

服务器启动没有问题。但是当我启动客户端时,我得到了错误:

Remote object threw exception java.rmi.UnmarshalException: error unmarshalling return; nested exception is: 
    java.lang.ClassNotFoundException: fiboserver.IFibonacci

对 *** 的搜索使我确信这与 RMI 注册表错误或策略文件错误有关。但是我知道策略文件被正确读取,我认为它们没有任何错误。

我做错了什么?为什么这不起作用?


编辑:

IFibonacci.java:

package fiboserver;

import java.math.BigInteger;
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface IFibonacci extends Remote
    public BigInteger getFibonacci(int n) throws RemoteException;
    public BigInteger getFibonacci(BigInteger n) throws RemoteException;

JAR 文件:

FibonacciClient.jar 的内容:

|META-INF
|----Manifest.mf
|fiboclient
|----FibonacciClient.class

FibonacciServer.jar 的内容:

|META-INF
|----manifest.mf
|fiboserver
|----IFibonacci.class
|----FibonacciServer.class
|----Fibonacci.class

【问题讨论】:

您正在远程注册表中绑定Fibonaci 对象,但尝试在客户端中查找IFibonacci 对象。另外,IFibonacci 类是否存在于客户端中?? @prasanth 世界上每个 RMI 程序都这样做。实现对象不在注册表中,在客户端也不可用。它是远程的,可以通过其远程接口访问。这就是整个想法。 IFibonacci 在服务器中可用吗?您是否在注册表中绑定了正确的对象并从客户端查找相同的对象?? @prasanth 如果该类在服务器上不可用,它将无法启动。他正在绑定正确的对象并正确查找它。请停止猜测。 在客户端或服务器中某处提到的类不可用。你可能想调查一下。为了您的信息,我不是在猜测。我试图通过指出您可能无意中错过的内容来帮助您 【参考方案1】:

客户端的类路径中没有异常中命名的类。您需要部署它,以及它所依赖的任何类,以此类推,直到关闭。

您可能已将远程接口重命名/复制到客户端的另一个包中。你不能那样做。服务器和客户端必须相同。相同的名称,相同的方法,相同的包。

NB 您的客户端“远程对象引发异常”中的消息不正确。可能是lookup() 抛出异常。不要通过假设可能并非如此的事情来迷惑自己。只需打印实际的错误消息、异常和堆栈跟踪。

【讨论】:

哦,伙计,所以你是在告诉我进口很重要?稍等,我将在示例中添加更多信息! 不,我告诉你包名很重要。只需阅读我实际写的内容。 我已经添加了客户端、服务器和 IFibonacci 接口的完整代码(目前在服务器项目中)。我想我没有弄乱包名。你能确认一下吗? 好的,我编辑了我的问题以获得有关项目的更多详细信息。我想这已经很清楚了。我正在听取有关如何解决此问题的任何建议! 我正在使用 Netbeans,它通过复制代码并将代码提供给需要它的项目来“自动”链接项目。 Eclipse 有一个“链接”项目的类似选项。也许这就是问题的根源?如果是这样,如何在不使用任何 IDE 选项的情况下修复它?

以上是关于RMI 客户端无法查找服务器 - java.rmi.UnmarshalException的主要内容,如果未能解决你的问题,请参考以下文章

RMI 客户端显示 java.rmi.NotBoundException 错误

“java.rmi.Remote 无法解析为类型”是啥意思?

Java RMI 和 netstat 输出

JUnit 和 RMI 应用程序的最佳实践,RMI 注册表

RMI 使用笔记

JAVA RMI远程通讯