HttpClient thread stuck in processData / unwrapBuffer after request processed

XMLWordPrintable

    • x86_64
    • linux

      ADDITIONAL SYSTEM INFORMATION :
      Linux node1 6.1.0-41-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.158-1 (2025-11-09) x86_64 GNU/Linux

      openjdk version "17.0.17" 2025-10-21
      OpenJDK Runtime Environment (build 17.0.17+10-Debian-1deb12u1)
      OpenJDK 64-Bit Server VM (build 17.0.17+10-Debian-1deb12u1, mixed mode, sharing)

      A DESCRIPTION OF THE PROBLEM :
      Occasionally, after processing HTTPS connections using HttpClient, we notice that some HttpClient threads become stuck and consume 100% CPU. The requests themselves complete successfully, and there are no active application threads, but the stuck HttpClient threads remain in this state indefinitely. The only way to recover is by restarting the JVM.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      I cannot provide specific steps to reproduce the issue. Our application regularly connects to a remote service, and these connections occasionally (every few days) result in stuck threads.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The TLS after-body read should never get stuck.
      ACTUAL -
      The HttpClient thread stuck causing 100% CPU usage. You can see 3 example stack traces in the "Confidential info" section.

      ---------- BEGIN SOURCE ----------

      // Create custom executor
      ExecutorService executor = Executors.newCachedThreadPool(new DefaultThreadFactory("HttpUtil"));
      Executor loggingExecutor = command -> {
      Runnable runnable = () -> {
      Thread t = Thread.currentThread();
      String oldName = t.getName();
      String newName = oldName + "-" + caller;

      t.setName(newName);
      try {
      command.run();
      } finally {
      t.setName(oldName);
      }
      };

      executor.execute(runnable);
      };

      // Create builder
      HttpClient.Builder builder = HttpClient.newBuilder()
      .version(HttpClient.Version.HTTP_1_1)
      .followRedirects(HttpClient.Redirect.NORMAL)
      .connectTimeout(Duration.ofSeconds(15))
      .proxy(ProxySelector.getDefault())
      .sslParameters(new SSLParameters())
      .cookieHandler(new CookieManager());
      .executor(loggingExecutor);

      X509TrustManager trustAllCert = new X509TrustManager() {
      @Override
      public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
      // Accept all
      }

      @Override
      public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
      // Accept all
      }

      @Override
      public java.security.cert.X509Certificate[] getAcceptedIssuers() {
      return new java.security.cert.X509Certificate[]{};
      }
      };

      TrustManager[] trustAllCerts = new TrustManager[] { trustAllCert };

      SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
      sslContext.init(null, trustAllCerts, new java.security.SecureRandom());

      builder.sslContext(sslContext);

      // Create client
      HttpClient client = builder.build();

      HttpRequest.Builder builder = HttpRequest.newBuilder()
      .POST(BodyPublishers.ofByteArray(content))
      .uri(URI.create(url))
      .timeout(Duration.ofMillis(DEFAULT_READ_TIMEOUT))
      .header("Content-Type", "application/json");

      HttpRequest request = builder.build();
      HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
      ---------- END SOURCE ----------

            Assignee:
            Jaikiran Pai
            Reporter:
            Patricia Tavares
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: