Java中的非法远程方法

49

这是我第一次使用Java Rmi*。我有一个自定义的类,它扩展了UnicastRemoteObject并实现了扩展remote接口。我认为我已经在类中正确地实现了接口的方法,但当我尝试运行我的代码时,仍然会收到IllegalArgumentException的错误消息(而且这是关于一个没有参数的方法)。

JVM声称遇到了非法远程方法,但该方法及其实现在我看来似乎没有问题。

除了错误地实现或调用该方法之外,还有其他可能导致此异常发生的原因吗?


以下是堆栈跟踪:

SEVERE: null
java.rmi.server.ExportException: remote object implements illegal remote interface; nested exception is:
        java.lang.IllegalArgumentException: illegal remote method encountered: public abstract java.lang.String Node.getId()
        at sun.rmi.server.UnicastServerRef.exportObject(Unknown Source)
        at java.rmi.server.UnicastRemoteObject.exportObject(Unknown Source)
        at java.rmi.server.UnicastRemoteObject.exportObject(Unknown Source)
        at java.rmi.server.UnicastRemoteObject.<init>(Unknown Source)
        at java.rmi.server.UnicastRemoteObject.<init>(Unknown Source)
        at NodeImpl.<init>(NodeImpl.java:30)
        at NodeLauncher.main(NodeLauncher.java:11)
Caused by: java.lang.IllegalArgumentException: illegal remote method encountered: public abstract java.lang.String Node.getId()
        at sun.rmi.server.Util.checkMethod(Unknown Source)
        at sun.rmi.server.Util.getRemoteInterfaces(Unknown Source)
        at sun.rmi.server.Util.getRemoteInterfaces(Unknown Source)
        at sun.rmi.server.Util.createProxy(Unknown Source)
        ... 7 more

这是接口:

import java.rmi.*;
import java.util.LinkedList;

interface Node extends Remote
{
    public boolean isAlive();

    public LinkedList<NodeImpl> getLeafNodes();

    public LinkedList<NodeImpl> getNeighborhoodList();

    public String [] getRoutingTable();

    public NodeImpl initiation(String credentials,Object application);

        public String route(String message,String key);

        public void inform(byte [] id);

        public String getId();

        public boolean isConnected();

        public void applicationClose();

        public boolean distanceMeasure();
}

这是这个类的构造函数:

public NodeImpl() throws RemoteException
    {
        super();
        l=4;
        M=1;
        nodeId=new byte [16];
        Random r=new Random();
        r.nextBytes(nodeId);
        leafNodes=new LinkedList<NodeImpl>();
        connected=false;
        ng=new NodeGUI(this);

        for(int i=0;i<l;i++)
        {
            leafNodes.add(null);
        }

        neighborhoodList=new LinkedList<NodeImpl>();
        anyNodeWhoAnswered=new LinkedList<byte []>();
        it=new InformingTimer(this);
        Thread informingTimerThread=new Thread(it);
        informingTimerThread.start();

        try 
        {
            Naming.rebind("rmi://" + "localhost" + ":1099/"+nodeId, this);
        }
        catch (Exception ex) 
        {
            Logger.getLogger(NodeImpl.class.getName()).log(Level.SEVERE, null, ex);
        }

        bootstrap();
    }

你应该已经成功连接了RMI注册表并查找到了远程对象,对吧?你能提供一下堆栈跟踪信息(在客户端/服务器端)吗? - padis
堆栈跟踪和一些代码可能有助于回答这个问题。 - Joel
异常发生在我尝试绑定远程对象之前。它发生在远程对象的构造函数那一行,我调用UnicastRemoteObject的构造函数并使用super()。我刚刚检查了API,并看到UnicastRemoteObject有一个没有参数的构造函数,所以我不明白问题出在哪里。 - Range
1个回答

87

所有RMI Remote接口上的方法都必须在其throws子句中声明RemoteException,例如:

public String getId() throws RemoteException;

不清楚为什么异常名称特别是 getId(),可能只是它首先被检查的方法。

此外,getLeafNodes()getNeighborhoodList()方法应该具有指定Node而非NodeImpl的返回类型,否则它们也很可能会失败。


1
为什么需要包含它...背后的机制是什么..? - guru_001
@guru_001 这样 RMI 运行时就可以将它抛出,以便处理在 RMI 内而不是远程对象中发生的错误。 - user207421
如果有一个未经检查的RemoteException变体可供使用,那将是很好的。这使得使用现有接口作为远程服务变得困难。 - Fr Jeremy Krieg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接