3

I have the following warning in Tomcat 8.5 I'm not sure I can ignore

WARNING [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [AppName] appears to have started a thread named [pool-20-thread-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
java.net.SocketInputStream.socketRead0(Native Method)
java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
java.net.SocketInputStream.read(SocketInputStream.java:171)
java.net.SocketInputStream.read(SocketInputStream.java:141)
sun.security.ssl.InputRecord.readFully(InputRecord.java:465)
sun.security.ssl.InputRecord.read(InputRecord.java:503)
sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:983)
sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)
sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)

It happens on connect in the following code:

URL url = new URL(MY_URL);
URLConnection con = url.openConnection();
HttpURLConnection http = (HttpURLConnection) con;
http.setRequestMethod("POST");
http.setDoOutput(true);
http.setFixedLengthStreamingMode(out.length);
http.setRequestProperty("Content-Type", "application/json");
http.connect();
try (OutputStream os = http.getOutputStream()) {
    os.write(out);
}

Should I add a finally with closing the InputStream:

http.getInputStream().close();

Or this code should be upgraded/converted to use URIBuilder and HttpHost?

EDIT The code executed every X seconds using Spring's @Scheduled

Ori Marko
  • 56,308
  • 23
  • 131
  • 233
  • 1
    You should `disconnect` the `URLConnection` when you are done. – M. Deinum Aug 13 '18 at 08:25
  • @M.Deinum I'm sending every few seconds the request, Isn't `disconnect` prevent reuse connection? – Ori Marko Aug 13 '18 at 08:26
  • You aren't reusing anything here, you are opening a connection each time you need one. – M. Deinum Aug 13 '18 at 08:26
  • Can you please post the entire stack trace? Also your exception could be caused by code run in a non-manged thread, are you doing some manual thread setup e.g. custom `ExecutorService`? – Karol Dowbecki Aug 13 '18 at 08:39
  • @KarolDowbecki next line is `http.connect();` shown in code, about threads, I'm just using Spring's `@Scheduled` – Ori Marko Aug 13 '18 at 08:44

1 Answers1

1

You are using @Scheduled within Tomcat to spawn threads. You must ensure that these threads will finish when the ServletContext is destroyed e.g. WAR being undeployed, Tomcat warns you about this. The HTTP request code is unrelated as URLConnection doesn't start new threads to perform the request.

One way to make Tomcat happy is to use daemon threads, as explained in this answer. This can be done with custom taskScheduler bean:

@Configuration
@EnableScheduling
public class TaskConfiguration {

  @Bean(destroyMethod = "shutdown")
  public Executor taskScheduler() {
    return Executors.Executors.newFixedThreadPool(4,
        new ThreadFactory() {
          public Thread newThread(Runnable r) {
            Thread t = Executors.defaultThreadFactory().newThread(r);
            t.setDaemon(true);
            return t;
          }
        });
  }

}
Karol Dowbecki
  • 43,645
  • 9
  • 78
  • 111
  • @user7294900 the code looks fine, `HttpURLConnection.disconnect()` is not guaranteed to have desired side effects as per method javadoc. You might want to dig into JVM to understand HTTP connection KeepAlive semantics. – Karol Dowbecki Aug 13 '18 at 09:17
  • I found also spring related answer https://stackoverflow.com/questions/10300403/scheduled-tasks-keep-jvm-hanging-when-standalone-program-wants-to-exit-jvm-nee – Ori Marko Sep 25 '18 at 07:43