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

BlueJ中发起HTTP请求抛出SSLHandshakeException问题求助

BlueJ中HTTP请求SSL握手异常问题解决

问题描述

编写的简单HTTP GET请求程序在BlueJ外部运行正常,但在BlueJ内执行时抛出javax.net.ssl.SSLHandshakeException异常,核心原因是java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty,说明BlueJ自带JDK的信任证书库存在问题。

测试代码

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class Test2 {

    private static final String POSTS_API_URL = "https://jsonplaceholder.typicode.com/posts";
    
    public static void main(String[] args) throws IOException, InterruptedException {
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                                .GET()
                                .header("accept", "application/json")
                                .uri(URI.create(POSTS_API_URL))
                                .build();
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println(response.body());
    }
}

抛出的异常信息

javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake
    at java.net.http/jdk.internal.net.http.HttpClientImpl.send(HttpClientImpl.java:956)
    at java.net.http/jdk.internal.net.http.HttpClientFacade.send(HttpClientFacade.java:133)
    at Test2.main(Test2.java:18)
Caused by: javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake
    at java.net.http/jdk.internal.net.http.common.SSLTube.checkForHandshake(SSLTube.java:595)
    at java.net.http/jdk.internal.net.http.common.SSLTube$SSLTubeFlowDelegate.checkForHandshake(SSLTube.java:156)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Writer.processData(SSLFlowDelegate.java:866)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Writer$WriterDownstreamPusher.run(SSLFlowDelegate.java:721)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(SequentialScheduler.java:149)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:207)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:280)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:233)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Writer.schedule(SSLFlowDelegate.java:758)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate.resumeActivity(SSLFlowDelegate.java:1068)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate.lambda$executeTasks$3(SSLFlowDelegate.java:1167)
    at java.net.http/jdk.internal.net.http.HttpClientImpl$DelegatingExecutor.execute(HttpClientImpl.java:177)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate.executeTasks(SSLFlowDelegate.java:1143)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate.doHandshake(SSLFlowDelegate.java:1109)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Reader.processData(SSLFlowDelegate.java:508)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Reader$ReaderDownstreamPusher.run(SSLFlowDelegate.java:283)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$LockingRestartableTask.run(SequentialScheduler.java:182)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(SequentialScheduler.java:149)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$TryEndDeferredCompleter.complete(SequentialScheduler.java:324)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(SequentialScheduler.java:151)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:207)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
    at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
    at java.base/sun.security.validator.PKIXValidator.<init>(PKIXValidator.java:97)
    at java.base/sun.security.validator.Validator.getInstance(Validator.java:173)
    at java.base/sun.security.ssl.X509TrustManagerImpl.getValidator(X509TrustManagerImpl.java:308)
    at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrustedInit(X509TrustManagerImpl.java:183)
    at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:254)
    at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:144)
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1296)
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.onConsumeCertificate(CertificateMessage.java:1195)
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.consume(CertificateMessage.java:1138)
    at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:393)
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:476)
    at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1273)
    at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1260)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:714)
    at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask.run(SSLEngineImpl.java:1205)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate.lambda$executeTasks$3(SSLFlowDelegate.java:1148)
    ... 13 more
Caused by: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
    at java.base/java.security.cert.PKIXParameters.setTrustAnchors(PKIXParameters.java:200)
    at java.base/java.security.cert.PKIXParameters.<init>(PKIXParameters.java:120)
    at java.base/java.security.cert.PKIXBuilderParameters.<init>(PKIXBuilderParameters.java:104)
    at java.base/sun.security.validator.PKIXValidator.<init>(PKIXValidator.java:94)
    ... 29 more

环境详情

  • BlueJ版本:5.4.1
  • 构建ID:76ffe5af
  • Java版本:21.0.4
  • 虚拟机:OpenJDK 64-Bit Server VM 21.0.4+7-LTS(Eclipse Adoptium)
  • JavaFX版本:20.0.2+3
  • 运行系统:Linux 5.15.0-130-generic(amd64)

解决方案

方案1:修复BlueJ自带JDK的信任证书库

  1. 找到BlueJ自带JDK的安装路径,通常在BlueJ安装目录下的jdk文件夹
  2. 进入jdk/lib/security目录,检查cacerts文件是否存在或为空
  3. 如果文件为空或损坏,可从系统已安装的正常JDK中复制cacerts文件替换它,或使用keytool命令重新导入根证书:
    keytool -import -alias root -keystore cacerts -file /path/to/root/certificate.crt
    
    默认cacerts密码为changeit

方案2:指定系统JDK运行BlueJ

修改BlueJ的启动配置,让它使用系统中已验证可用的JDK:

  1. 找到BlueJ的启动脚本(Linux下通常是bluej或bluej.sh)
  2. 在脚本开头添加JAVA_HOME环境变量指向系统JDK路径:
    export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
    export PATH=$JAVA_HOME/bin:$PATH
    
  3. 保存后重新启动BlueJ

方案3:代码中忽略SSL证书验证(仅测试环境使用)

不推荐生产环境使用,仅用于临时测试:
修改HttpClient的创建逻辑,添加自定义TrustManager跳过证书验证:

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class Test2 {

    private static final String POSTS_API_URL = "https://jsonplaceholder.typicode.com/posts";
    
    public static void main(String[] args) throws IOException, InterruptedException {
        // 创建信任所有证书的TrustManager
        TrustManager[] trustAllCerts = new TrustManager[]{
            new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() { return null; }
                public void checkClientTrusted(X509Certificate[] certs, String authType) {}
                public void checkServerTrusted(X509Certificate[] certs, String authType) {}
            }
        };

        try {
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustAllCerts, new SecureRandom());
            
            HttpClient client = HttpClient.newBuilder()
                    .sslContext(sslContext)
                    .build();

            HttpRequest request = HttpRequest.newBuilder()
                                    .GET()
                                    .header("accept", "application/json")
                                    .uri(URI.create(POSTS_API_URL))
                                    .build();
            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
            System.out.println(response.body());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 03:04:51