代码之家  ›  专栏  ›  技术社区  ›  Marco Boom

Java RMI在对存根调用函数时冻结

  •  -1
  • Marco Boom  · 技术社区  · 8 年前

    总结

    我正在进行一个项目,发现了以下问题:

    我们在代码中发现了一个无法解决的问题。 首先,我们给出了有关Eclipse项目以及如何执行它的一些一般信息,然后给出了有关代码的一些详细信息,最后描述了问题。

    项目

    我们在Eclipse中构建了一个Java Maven项目。它包含两个源文件夹:src/main/java和src/test/java。主文件夹包含Gallager、Humblet和Spira算法的实现。目前,我们有一个测试SimpleTest,看看算法的基本功能是否如预期的那样工作。 代码可按如下方式执行:

    1. 解压缩所附文件DA-Lab3。拉链
    2. 打开DA-Lab3/target/classes文件夹中的命令/终端窗口。
    3. 在此目录中启动Java RMI注册表(Linux中为–rmiregistry,Windows中为–Start rmiregistry)。
    4. 转到命令/终端窗口中的文件夹DA-Lab3。
    5. 执行:mvn clean install-f。”. (如果由于maven无法清理文件夹而无法执行此操作,请在没有–clean–offer的情况下尝试相同的命令。) 现在,测试文件应该由Java/Maven执行。

    代码

    代码分为几个部分。需要了解的最重要的部分是节点、流程和RMINetwork。 节点包含实际的算法,流程通过创建边、实现发送方法和删除边等实用功能扩展节点。RMINetwork处理与RMI相关的功能,如在注册表中注册进程、注销进程以及在RMINetwork中查找其他进程。

    节点放置在GHS中。图形包。该包还包含Edge、NodeEstate和EdgeState。 消息由接收功能处理(第221行)。每种类型的消息都实现了GHS接口。信息。IMessage with the function process。节点中的receive函数在每条消息中调用此process函数。从消息中的这些处理函数调用节点中的特定函数。节点中的这些函数根据算法处理消息。

    流程放在GHS包中。它使用id变量扩展节点,并提供函数send、connect、disconnect、id()、run和stop。send函数确定接收者的id,并向RMINetwork提供向接收者发送消息的任务。 Process类还实现了IProcess接口。RMI客户端使用此接口。

    RMINetwork位于包通信中。此类包含用于注册、注销、查找和发送的函数。

    问题所在

    在SimpleTest test1中,创建了三个进程和一个边缘。进程0连接到进程2。然后进程0唤醒并向进程2发送连接消息。进程2唤醒并将连接消息发送回进程0。然后,进程0向进程2发送启动消息。但在这里,Java似乎没有抛出任何错误。

    详细说明: Java似乎停留在: ((IProcess) this.lookup(id)).receive(edge, message); r网络:52。

    为了了解实际问题是什么,我们向函数中添加了一些测试代码。 在第49行,我们添加了: IProcess p = (IProcess) this.lookup(id); 和第50行: String s = p.id(); 第51行: System.out.println("networking"); 通过启用此测试代码,Java Stuck位于第50行。

    当第50行被禁用时,执行第51行,Java在第52行停止。

    p.id()函数是在进程中实现的。第一条语句将字符串打印到命令行。在Java停止时,不会执行这个print语句。

    当我们将第49行替换为49行时,我们添加了: IProcess p = (IProcess) this.lookup(edge.neighbour(id)); (发送方现在实际上正在查找自己的id),然后在发送第二条而不是第三条消息时出现问题。

    因此,Java RMI似乎在对存根的调用中冻结。但它始终适用于第一条消息,并根据第49行的不同,适用于第二条消息。因为没有抛出错误,所以我们不知道为什么RMI此时会冻结。

    @Override
    public void send(String id, Edge edge, IMessage message) throws Exception {
        System.out.println("testing");
        IProcess p = (IProcess) this.lookup(id);
        String s = p.id();
        //System.out.println(((IProcess) this.lookup(id)).id());
        System.out.println("networking");
        ((IProcess) this.lookup(id)).receive(edge, message);
        System.out.println("id found");
    }
    

    我们希望你能帮助我们。

    您可以在以下位置查看所有代码: https://github.com/mboom/DA-Lab3

    2 回复  |  直到 6 年前
        1
  •  0
  •   user207421    8 年前

    您调用的远程方法没有返回。

        2
  •  0
  •   Marco Boom    8 年前

    结果表明,这些进程在单个线程中相互等待。向其他进程发送消息的旧启动方法目前尚未完成,另一个进程通过存根调用方法。只要旧方法还在运行,这些方法就不会启动。因为旧方法正在等待响应(只有当这些旧方法完成时才会出现响应),所以系统最终会陷入死锁。我们通过在新线程中执行节点的接收方法来解决这个问题。

    推荐文章