Когда я использую WebClient в не загружаемом устаревшем приложении JEE, работающем на Tomcat. Похоже, я получаю это при завершении работы
Mar 17, 2020 8:46:25 PM org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
WARNING: The web application [ROOT] appears to have started a thread named [reactor-http-epoll-4] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
io.netty.channel.epoll.Native.epollWait(Native Method)
io.netty.channel.epoll.Native.epollWait(Native.java:129)
io.netty.channel.epoll.Native.epollWait(Native.java:122)
io.netty.channel.epoll.EpollEventLoop.epollWaitNoTimerChange(EpollEventLoop.java:290)
io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:347)
io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
java.base@11.0.4/java.lang.Thread.run(Thread.java:834)
Однако я не могу найти какой-либо способ "очистки" или завершения процесса netty, который он использует.
У меня уже есть следующее в методе @PreDestroy, но, похоже, не помогает.
FastThreadLocal.removeAll();
Class.forName("io.netty.util.internal.InternalThreadLocalMap").getMethod("destroy").invoke(null);
Я использовал WebClient для передачи файла во внешнюю конечную точку сервиса миниатюр с помощью данных формы, но оттуда я не Не вижу точки утечки.
public Path createThumbnail(final Path src) {
final MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder();
bodyBuilder.part("file", new PathResource(src));
Path thumbnailPath = computeThumbnailPath(src);
final WebClient webClient = WebClient.create("http://thumbnail-generator:8080/api/upload/file");
webClient.post()
.contentType(MediaType.MULTIPART_FORM_DATA)
.body(BodyInserters.fromMultipartData(bodyBuilder.build()))
.exchange()
.flatMap(r -> r.bodyToMono(ByteArrayResource.class))
.map(r -> {
try (final InputStream s = r.getInputStream()) {
return Files.copy(s, thumbnailPath);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
})
.block();
return thumbnailPath;
}