为何Hello RMI示例仅本人及root可用,其他用户无法使用?
RMI仅本人及root账户可用的问题排查求助
我使用RMI已有多年,目前在开发机上遇到一个问题,希望在移除RMI(我们不再需要RPC)前解决。不知哪里配置出错,现在RMI仅本人及root账户可用(无论防火墙是否关闭)。我耗时一周排查,最终测试了Oracle的Hello RMI示例:停止并禁用了rmiregistry及所有运行的Java程序,但其他用户执行时会先显示"host:localhost port:1099",随后触发知名错误"Server exception: java.rmi.ConnectException: Connection refused to host.",而使用sudo运行脚本则可正常连接。
测试启动脚本
#!/bin/bash # # port="$1" [[ $port = "" ]] && port="1099" ip="localhost" #ip="127.0.0.1" #sudo systemctl stop rmiregistry while true; do sudo netstat -a --numeric-ports|grep $port; if [ $? -eq 0 ]; then echo -e "$port is in use - waiting"; sleep 1; else break; fi; done JAVA_BIN="/usr/java/jdk/bin" $JAVA_BIN/javac -d "." *.java $JAVA_BIN/rmiregistry $port & rmiregistryPID=$! echo -n "rmiregistry:";ps -p $rmiregistryPID classDir="." #strace $JAVA_BIN/java -classpath $classDir \ -Djava.rmi.server.codebase=file:$classDir/ \ -Djava.rmi.server.hostname=$ip \ example.hello.Server $ip $port & serverPID=$! echo sleep 5;echo -e "\nServer PID:";ps -p $serverPID $JAVA_BIN/java -classpath $classDir example.hello.Client $ip $port clientPID=$!;kill $clientPID echo kill $rmiregistryPID; ps -p $rmiregistryPID kill $serverPID;ps -p $serverPID
Hello.java
package example.hello; import java.rmi.Remote; import java.rmi.RemoteException; public interface Hello extends Remote { String sayHello() throws RemoteException; }
Server.java
package example.hello; import java.rmi.registry.Registry; import java.rmi.registry.LocateRegistry; import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; public class Server extends UnicastRemoteObject implements Hello { public Server() throws RemoteException {} public String sayHello() throws RemoteException { try { return "Hello, world!"; } catch (Exception ex) { System.err.println("Server exception: " + ex.toString()); ex.printStackTrace(); return "error"; } } public static void main(String args[]) { try { String host = (args.length < 1) ? "127.0.0.1" : args[0]; String portString = (args.length < 2) ? "1099" : args[1]; int port = Integer.parseInt(portString); System.out.println("host:"+host+" port:"+port); Server obj = new Server(); //LocateRegistry.createRegistry(port); String name = "//"+host+":"+port+"/Hello"; Naming.rebind(name, obj); System.out.println("Server ready; host:"+host+" port:"+port); } catch (Exception ex) { System.err.println("Server exception: " + ex.toString()); ex.printStackTrace(); } } }
Client.java
package example.hello; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; public class Client { private Client() {} public static void main(String[] args) { String host = (args.length < 1) ? null : args[0]; String portString = (args.length < 2) ? "1099" : args[1]; int port = Integer.parseInt(portString); System.out.println("host:"+host+" port:"+port); try { Registry registry = LocateRegistry.getRegistry(host, port); Hello stub = (Hello) registry.lookup("Hello"); String response = stub.sayHello(); System.out.println("\nresponse: " + response); } catch (Exception e) { System.err.println("Client exception: " + e.toString()); e.printStackTrace(); } } }
已完成的排查动作
- 复制示例目录并将所有内容改为其他用户所有,结果无差异
- 对服务器进程使用strace分析,未发现异常线索
- 尝试切换其他端口测试,问题依旧;默认1099端口已使用多年
- 关闭防火墙测试,问题未解决
补充说明
示例仅本人及root账户可正常运行,异常触发点在服务器尝试绑定到rmiregistry时。后续计划尝试由root启动服务器(我们的系统原本会在开机时自动启动注册表及服务器)。
内容的提问来源于stack exchange,提问作者William Dickerson
相关产品推荐
相关产品推荐

