Java 8迁移至Java 17遇sun.security包不可见问题求解决方案
解决Java 8迁移至Java 17时PKCS#10相关内部API不可用问题
问题原因
你依赖的sun.security.pkcs10.PKCS10和sun.security.x509.X500Name属于Java内部私有API,从Java 9开始就被标记为受限访问,Java 17中已完全移除,因此编译和运行时会出现包不可见的错误。
推荐解决方案:使用BouncyCastle密码学库替代
BouncyCastle是业界广泛认可的开源密码学库,提供了完整且稳定的PKCS#10证书请求生成支持,不受Java版本迭代影响。
步骤1:添加BouncyCastle依赖
如果使用Maven,在pom.xml中添加:
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk15on</artifactId> <version>1.77</version> <!-- 建议使用最新稳定版 --> </dependency>
步骤2:替换原有实现代码
以下代码完全替代原逻辑,生成与原代码格式一致的PEM编码PKCS#10请求:
import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.cert.jcajce.JcaPKCS10CertificationRequestBuilder; import org.bouncycastle.operator.ContentSigner; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import org.bouncycastle.pkcs.PKCS10CertificationRequest; import org.bouncycastle.util.io.pem.PemWriter; import java.io.StringWriter; import java.security.KeyPair; import java.security.Security; import java.security.cert.X500Principal; import java.nio.charset.StandardCharsets; private static byte[] encodeAndSignRequest(KeyPair keyPair, String signatureAlgorithm, X500Principal principal) throws Exception { // 注册BouncyCastle安全提供者 Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); // 转换X500Principal为BouncyCastle的X500Name X500Name subject = new X500Name(principal.getName()); // 创建签名器 ContentSigner contentSigner = new JcaContentSignerBuilder(signatureAlgorithm) .setProvider("BC") .build(keyPair.getPrivate()); // 构建PKCS#10证书请求 JcaPKCS10CertificationRequestBuilder requestBuilder = new JcaPKCS10CertificationRequestBuilder(subject, keyPair.getPublic()); PKCS10CertificationRequest pkcs10Request = requestBuilder.build(contentSigner); // 编码为PEM格式(与原代码输出格式一致) StringWriter writer = new StringWriter(); try (PemWriter pemWriter = new PemWriter(writer)) { pemWriter.writeObject(new org.bouncycastle.util.io.pem.PemObject("CERTIFICATE REQUEST", pkcs10Request.getEncoded())); } return writer.toString().getBytes(StandardCharsets.UTF_8); }
代码说明
- 移除了对
Signature参数的直接依赖,改为传入签名算法字符串(如SHA256withRSA),更符合BouncyCastle的API设计;若需保留原参数,可通过signature.getAlgorithm()获取算法字符串。 - 使用
PemWriter生成标准PEM格式的证书请求,与原代码pkcs10.print(printStream)的输出格式完全一致。 - BouncyCastle的API均为公开稳定接口,不会因Java版本升级出现兼容性问题。
不推荐的临时方案
若因特殊情况需临时兼容,可通过JVM启动参数--add-exports java.base/sun.security.pkcs10=ALL-UNNAMED和--add-exports java.base/sun.security.x509=ALL-UNNAMED强制开放内部API,但该方案违反Java封装原则,后续Java版本可能彻底失效,不建议长期使用。
内容的提问来源于stack exchange,提问作者mayur gavali
相关产品推荐
相关产品推荐

