Java 8升级后RMI Registry连接遇AccessControlPermission权限问题
解决Java 8升级后RMI客户端的AccessControlException权限问题
报错信息:
java.security.AccessControlException: access denied ("java.net.SocketPermission" "localhost:1099" "listen,resolve")
问题背景
代码最初基于Java 6及更低版本开发,升级到Java 8后,因Java 8安全策略更严格,建立RMI Registry连接时抛出上述权限错误,已尝试在java.policy文件中为默认RMI端口1099授予权限,但问题未解决。客户端核心代码如下:
package com.aurionpro.reuters; import com.aurionpro.reuters.service.UpdateCurrencyRates; import java.io.IOException; import java.rmi.NotBoundException; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.util.Properties; public final class RMIServiceClient { private final String hostname; private final int port; private final String serviceName; private UpdateCurrencyRates currencyRates; private Registry registry = null; public RMIServiceClient(String appPropFileName, String productName) { Properties properties = new Properties(); ClassLoader loader = Thread.currentThread().getContextClassLoader(); try { properties.load(loader.getResourceAsStream(appPropFileName)); } catch (IOException var6) { var6.printStackTrace(); } this.hostname = properties.getProperty("rmiclient." + productName + ".registry.host"); this.port = Integer.parseInt(properties.getProperty("rmiclient." + productName + ".registry.port")); this.serviceName = properties.getProperty("rmiclient." + productName + ".registry.serviceName"); } public UpdateCurrencyRates getCurrencyRatesService() throws RemoteException, NotBoundException { SecurityManager securityManager = new SecurityManager(); System.setSecurityManager(securityManager); this.registry = LocateRegistry.getRegistry(this.hostname, this.port); this.currencyRates = (UpdateCurrencyRates)this.registry.lookup(this.serviceName); return this.currencyRates; } }
问题分析
- 权限配置误区:之前给
java.policy配置的是listen,resolve权限,但RMI客户端是主动连接Registry,需要的是connect,resolve权限,listen是服务端绑定端口时才需要的权限,客户端不需要。 - 手动设置SecurityManager:Java 8中,客户端场景下默认不需要手动设置
SecurityManager,手动设置后会强制启用严格的权限检查,反而会拦截正常的RMI连接操作。
解决方案
方案1:移除手动配置的SecurityManager(推荐)
客户端场景下,Java 8默认的安全策略已经足够支持RMI连接,不需要额外设置SecurityManager。直接注释或删除以下两行代码:
// SecurityManager securityManager = new SecurityManager(); // System.setSecurityManager(securityManager);
修改后重新运行客户端,即可正常连接RMI Registry。
方案2:完善java.policy权限配置(若必须保留SecurityManager)
如果业务场景要求必须启用SecurityManager,需要修正java.policy的权限配置,添加客户端所需的连接权限:
grant { // 允许连接本地1099端口的RMI Registry permission java.net.SocketPermission "localhost:1099", "connect,resolve"; // 允许连接本地所有端口(应对RMI动态端口的情况) permission java.net.SocketPermission "localhost:*", "connect,resolve"; // 如果RMI服务在远程主机,添加对应主机的权限 permission java.net.SocketPermission "your-rmi-server-host:*", "connect,resolve"; };
启动程序时,确保指定了正确的policy文件路径:
java -Djava.security.policy=/path/to/your/custom.policy com.aurionpro.reuters.RMIServiceClient
内容的提问来源于stack exchange,提问作者XERVIS
相关产品推荐
相关产品推荐

