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

问题描述 投票:-1回答:2

Summary

我正在研究一个项目并发现了这个问题:

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

The project

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

  1. 解压缩附件DA-Lab3.zip。
  2. 在DA-Lab3 / target / classes文件夹中打开命令/终端窗口。
  3. 在此目录中启动Java RMI Registry(在Linux中为“rmiregistry&”,在Windows中为“start rmiregistry”)。
  4. 转到命令/终端窗口中的DA-Lab3文件夹。
  5. 执行:“mvn clean install -f。”。 (如果这不起作用,因为maven无法清理文件夹,请尝试使用相同的命令而不使用“clean”。)现在,testfiles应该由Java / Maven执行。

The code

代码分为几个部分。要理解的最重要的部分是Node,Process和RMINetwork。 Node包含实际算法,Process extends Node具有创建边缘等实用功能,实现发送方法和删除边缘。 RMINetwork处理与RMI相关的功能,例如在注册表中注册进程,取消注册进程以及查找RMINetwork中的其他进程。

节点放在GHS.graph包中。该软件包还包含Edge,NodeState和EdgeState。消息由接收功能处理(行221)。每种类型的消息都使用函数进程实现接口GHS.messages.IMessage。 Node中的receive函数在每条消息中调用此过程函数。从消息中的这些过程函数中调用Node中的特定函数。 Node中的这些函数根据算法处理消息。

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

RMINetwork放在包通信中。该类包含注册,取消注册,查找和发送的功能。

The problem

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

进入细节:Java似乎停留在:((IProcess) this.lookup(id)).receive(edge, message); RMINetwork r:52。

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

当行50被禁用时,执行行51并且Java卡在行52处。

p.id()函数在Process中实现。第一个语句将字符串输出到命令行。在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

java maven rmi freeze
2个回答
0
投票

您调用的远程方法未返回。


0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.