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

非Android环境调用newTrustedTransport遇KeyStoreException:JKS实现未找到

解决IBM i JDK 1.6调用Google Spreadsheet API时的KeyStoreException问题

我之前在IBM i环境中处理过类似的Google API兼容性问题,你的报错核心是IBM i的J9 JVM在JDK 1.6版本下默认不使用JKS作为密钥库类型,而Google的GoogleNetHttpTransport.newTrustedTransport()底层硬编码依赖了JKS实现,导致CL调用时抛出异常(本地JVM可能默认是JKS所以正常)。下面是分步解决方法:

一、明确问题根源

IBM i的JDK 1.6(J9)默认密钥库类型通常是PKCS12而非JKS,且java.security配置中可能未注册Sun的JKS Provider。Google的SecurityUtils.getJavaKeyStore()方法直接调用KeyStore.getInstance("JKS"),在IBM i环境中找不到对应实现,就会抛出KeyStoreException。

二、具体解决方案

1. 手动构建HttpTransport(最可靠的方法)

绕过Google提供的newTrustedTransport(),手动基于IBM i JVM支持的默认密钥库构建SSL传输:

import com.google.api.client.http.javanet.NetHttpTransport;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.security.KeyStore;
import java.security.SecureRandom;

// 替换原来的GoogleNetHttpTransport.newTrustedTransport()调用
public static NetHttpTransport getCustomTransport() throws Exception {
    // 使用IBM i JVM默认的密钥库类型(通常是PKCS12)
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
    // 加载系统默认信任库
    ks.load(null, null);
    tmf.init(ks);
    
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());
    
    return new NetHttpTransport.Builder()
        .setSslSocketFactory(sslContext.getSocketFactory())
        .build();
}

然后在你的代码中用getCustomTransport()替代原来的GoogleNetHttpTransport.newTrustedTransport()即可。

2. 确保Google API依赖兼容JDK 1.6

JDK 1.6已经非常老旧,高版本的Google API客户端不再支持它。你需要在Gradle中指定兼容的版本:

dependencies {
    // 必须使用1.32.x版本,这是支持JDK 1.6的最后一个大版本
    implementation 'com.google.api-client:google-api-client:1.32.1'
    implementation 'com.google.oauth-client:google-oauth-client-jetty:1.32.1'
    implementation 'com.google.apis:google-api-services-sheets:v4-rev20220715-1.32.1'
}

构建Jar包时务必确认依赖没有引入高版本的JDK 1.7+兼容类。

3. 通过CL命令指定JVM参数(临时适配)

如果不想修改代码,可以在CL的RUNJVA命令中添加JVM参数,强制指定密钥库类型和Provider:

RUNJVA CLASS(prueba.Principal) JAVAOPT('-Dkeystore.type=JKS' '-Djava.security.provider=com.ibm.crypto.provider.IBMJCE')

注意:IBM i的JVM可能需要使用IBM自带的JCE Provider,而非Sun的,所以这里用com.ibm.crypto.provider.IBMJCE,如果不行可以尝试sun.security.provider.Sun(需要确认JVM中包含该Provider)。

4. 验证JVM的安全Provider(调试用)

如果不确定JVM支持哪些Provider,可以在代码中添加调试打印:

import java.security.Security;
import java.security.Provider;

// 在程序开头添加
for (Provider provider : Security.getProviders()) {
    System.out.println("Provider: " + provider.getName() + " | Info: " + provider.getInfo());
}

运行后查看输出,确认是否有支持JKS的Provider存在。

三、总结

最推荐的方案是手动构建HttpTransport,既避免了Google API对JKS的硬编码依赖,又适配了IBM i的JVM环境。同时一定要确保使用兼容JDK 1.6的Google API版本,否则还会出现其他兼容性问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:08:56