RMI跨机器调用报java.rmi.AccessException,远程绑定请求被拒绝
解决RMI Registry.rebind的AccessException问题
这个错误我之前在跨机器部署RMI应用时也碰到过,核心原因是RMI注册表默认只允许本地主机执行rebind/unbind这类修改注册表的操作,你的客户端IP(10.0.0.71)是远程主机,所以直接被拦截了。下面分两种场景给你解决方案:
场景1:客户端错误地执行了rebind操作(最常见情况)
正常的RMI流程里,rebind是服务器端的职责——服务器把实现类绑定到本地注册表,客户端只需要通过lookup获取远程对象即可。
检查并修正代码:
- 先排查你的客户端代码,是不是不小心写了类似这样的错误逻辑:
// 客户端错误代码示例 Registry registry = LocateRegistry.getRegistry("10.0.1.100"); registry.rebind("Calculator", someObject); // 客户端不该执行这个操作!
- 把
rebind逻辑完全移到服务器端,服务器端的正确绑定代码示例:
// 服务器端代码 package com.simplecalc.server; import com.simplecalc.commons.Calculator; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.UnicastRemoteObject; public class CalculatorImpl implements Calculator { @Override public float add(float a, float b) { return a + b; } public static void main(String[] args) { try { Calculator calc = new CalculatorImpl(); // 导出远程对象 Calculator stub = (Calculator) UnicastRemoteObject.exportObject(calc, 0); // 创建或获取本地注册表(默认端口1099) Registry registry = LocateRegistry.createRegistry(1099); // 将对象绑定到注册表 registry.rebind("Calculator", stub); System.out.println("Calculator server is ready"); } catch (Exception e) { e.printStackTrace(); } } }
- 客户端只需要通过
lookup获取远程对象并调用方法:
// 客户端正确代码示例 package com.simplecalc.client; import com.simplecalc.commons.Calculator; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; public class CalculatorClient { public static void main(String[] args) { try { // 连接服务器的RMI注册表 Registry registry = LocateRegistry.getRegistry("10.0.1.100", 1099); // 获取远程计算器对象 Calculator calc = (Calculator) registry.lookup("Calculator"); // 调用远程加法方法 float result = calc.add(3.2f, 5.8f); System.out.println("Addition result: " + result); } catch (Exception e) { e.printStackTrace(); } } }
场景2:确实需要远程操作注册表(不推荐,存在安全风险)
如果你的业务场景必须让远程客户端修改注册表,那需要通过安全策略文件开放权限:
- 在服务器端创建一个权限策略文件,比如命名为
rmi.policy,内容如下:
grant { permission java.security.AllPermission; };
- 启动RMI注册表时指定这个策略文件:
rmiregistry -J-Djava.security.policy=rmi.policy &
- 启动服务器JVM时也要指定策略和服务器的可访问IP(避免客户端拿到本地回环IP导致连接失败):
java -Djava.security.policy=rmi.policy -Djava.rmi.server.hostname=10.0.1.100 com.simplecalc.server.CalculatorImpl
额外注意事项
- 确保服务器的防火墙开放了RMI默认端口1099,以及RMI对象的通信端口;如果不想用随机端口,也可以通过
-Djava.rmi.server.port=xxxx参数固定端口,方便防火墙配置 - 服务器端必须设置
java.rmi.server.hostname为自身的可访问IP(10.0.1.100),否则客户端可能拿到服务器的本地回环IP(比如127.0.0.1),导致无法连接远程对象
内容的提问来源于stack exchange,提问作者RDV
相关产品推荐
相关产品推荐

