Java - HttpClient not releasing threads

2.4k views Asked by At

I am using Java 11's built in HTTP client and facing a strange issue with the client not releasing threads. I have the following code:

public static void main(String[] args) throws InterruptedException, IOException, URISyntaxException {
    HttpClient client = HttpClient.newBuilder().followRedirects(HttpClient.Redirect.ALWAYS).build();
    HttpResponse<Void> response;

    HttpRequest request = HttpRequest.newBuilder().uri(new URI("http://127.0.0.1:4321")).headers("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString("{}")).build();

    response = client.send(request, HttpResponse.BodyHandlers.discarding());
}

and I am running the application with maven's exec plugin but getting the following errors:

[WARNING] thread Thread[HttpClient-1-Worker-0,5,com.example.httpclient.App] was interrupted but is still alive after waiting at least 14995msecs
[WARNING] thread Thread[HttpClient-1-Worker-0,5,com.example.httpclient.App] will linger despite being asked to die via interruption
[WARNING] thread Thread[HttpClient-1-Worker-1,5,com.example.httpclient.App] will linger despite being asked to die via interruption
[WARNING] thread Thread[HttpClient-1-Worker-2,5,com.example.httpclient.App] will linger despite being asked to die via interruption
[WARNING] NOTE: 3 thread(s) did not finish despite being asked to  via interruption. This is not a problem with exec:java, it is a problem with the running code. Although not serious, it should be remedied.
[WARNING] Couldn't destroy threadgroup org.codehaus.mojo.exec.ExecJavaMojo$IsolatedThreadGroup[name=com.example.httpclient.App,maxpri=10]

It seems the client is not releasing its threads properly. Interestingly if I comment out the code that sends the request (while keeping the code that creates the client) then the above warnings go away.

If I add System.exit(0) at the end then the warnings go away too but I am still wondering why this is happening with the built-in client? There is no close method on the client, request or the response so I don't think I am leaking resources.

I even set the client to null and called GC manually even then the problem persists. Very confused whats going on.

1

There are 1 answers

6
daniel On

The HttpClient uses an internal thread pool with daemon threads. It seems the client doesn't explicitly shutdown this thread pool when it is garbage collected.

The warning you are seeing is related to the infrastructure put in place by your maven plugin. It seems others have experienced similar issues (see for instance couldn't destroy threadgroup org.codehaus.mojo.exec.ExecJavaMojo$IsolatedThreadGroup[name=SitemapCheck.SitemapAction,maxpri=10]).

A possible workaround to suppress the warning would be to supply an Executor to the HttpClient.Builder, and shutdown this Executor in your main method.

See https://docs.oracle.com/en/java/javase/15/docs/api/java.net.http/java/net/http/HttpClient.Builder.html#executor(java.util.concurrent.Executor)

For the record, if no executor is supplied to the HttpClient.Builder, the HttpClient uses an executor as returned by Executors.newCachedThreadPool(ThreadFactory).