You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JRE8下DGCClient抛出AccessControlException读取trustStore权限问题

问题

使用JRE 8环境,程序通过JavaService.exe作为Windows服务运行,已启用SecurityManager并指定包含相关权限的策略文件。在服务端与客户端完成握手连接且无I/O流存在时,自定义RMIClientSocketFactory中设置系统属性后出现权限异常。

自定义SocketFactory代码

public class CustomClientSocketFactory implements RMIClientSocketFactory, Serializable {
    @Override
    public Socket createSocket(String host, int port) throws IOException {
        
        SSLSocket socket = null;
        try {
            File tsFile = new File("truststore.pfx");
            
            FileInputStream is = AccessController.doPrivileged(new PrivilegedAction<FileInputStream>() {
                @Override
                public FileInputStream run() {
                    FileInputStream fs = null;
                    try {
                        fs = new FileInputStream(tsFile);
                    } catch (FileNotFoundException e) {
                        System.out.println("Expected file unfound: " + truststore + "; " + e.getMessage());
                    }
                    return fs;
                }
                
            });
            
            KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
            ks.load(is, phrase.toCharArray());
            
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            tmf.init(ks);
            
            SSLContext context = SSLContext.getInstance("TLS");
            context.init(null, tmf.getTrustManagers(), new SecureRandom());
            
            System.setProperty("javax.net.ssl.trustStore", "truststore.pfx");
            System.setProperty("javax.net.ssl.trustStorePassword", phrase);
            System.setProperty("javax.net.ssl.trustStoreType", "PKCS12");
                        
            SSLSocketFactory socketFactory = context.getSocketFactory();
            socket = (SSLSocket) socketFactory.createSocket(host, port);
            socket.setEnabledProtocols(new String[] {"TLSv1.2", "TLSv1.3"});
            socket.setEnabledCipherSuites(socket.getSupportedCipherSuites());
        } catch (Throwable t) {
            throw new IOException(t.getMessage(), t);
        }
        
        return socket;
    }
}

异常堆栈信息

java.security.AccessControlException: access denied ("java.util.PropertyPermission" "javax.net.ssl.trustStore" "read")
    at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
    at java.security.AccessController.checkPermission(AccessController.java:886)
    at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
    at java.lang.SecurityManager.checkPropertyAccess(SecurityManager.java:1294)
    at java.lang.System.getProperty(System.java:733)
...
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:617)
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216)
at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:343)
at sun.rmi.transport.DGCImpl_Stub.clean(DGCImpl_Stub.java:74)
at sun.rmi.transport.DGCClient$EndpointEntry.makeCleanCalls(DGCClient.java:700)
at sun.rmi.transport.DGCClient$EndpointEntry.access$1700(DGCClient.java:192)
at sun.rmi.transport.DGCClient$EndpointEntry$RenewCleanThread$1.run(DGCClient.java:610)
at sun.rmi.transport.DGCClient$EndpointEntry$RenewCleanThread$1.run(DGCClient.java:603)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.DGCClient$EndpointEntry$RenewCleanThread.run(DGCClient.java:603)
at java.lang.Thread.run(Thread.java:750)

策略文件配置

grant {
    permission java.security.AllPermission;         
    permission java.net.SocketPermission "localhost:1024-","connect,accept";         
    permission java.util.PropertyPermission "javax.net.ssl.trustStore","read";
};

解决方案

1. 移除不必要的系统属性设置

你的代码已经手动初始化了SSLContext并加载了信任库,完全不需要设置javax.net.ssl.trustStore相关全局系统属性——这些属性是给默认SSL上下文用的,你自定义的SSLContext不会读取它们,反而全局属性会被后续RMI的DGC(分布式垃圾回收)线程读取,触发SecurityManager的权限校验。直接删掉这三行代码:

System.setProperty("javax.net.ssl.trustStore", "truststore.pfx");
System.setProperty("javax.net.ssl.trustStorePassword", phrase);
System.setProperty("javax.net.ssl.trustStoreType", "PKCS12");

2. 修复策略文件的加载问题

你配置的AllPermission已经包含所有权限(包括PropertyPermission的读写),后面单独加的权限配置属于冗余。需要确保JavaService启动时明确指定策略文件的绝对路径——Windows服务运行时的工作目录可能不是程序所在目录,相对路径会导致策略文件无法加载。启动参数示例:

-Djava.security.manager -Djava.security.policy=file:C:/your/app/path/policyfile.policy

3. 确认DGC线程的权限上下文

异常是RMI的DGC线程读取全局SSL属性时触发的,只要你不设置这些全局属性,DGC线程就不会去读取它们,自然不会触发权限拒绝。这是解决问题的核心。

内容的提问来源于stack exchange,提问作者SophieW

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 21:58:13