Diagnosing and Solving a Tomcat Embedded 100 ms Delay Bug in Spring Boot Using Arthas

This article describes how a hidden 100 ms latency in a Spring Boot channel service was traced with Arthas, revealing a Tomcat‑embed bug caused by repeated loading of Swagger UI resources, and explains how upgrading Tomcat or Spring Boot eliminates the delay.

Top Architect
Top Architect
Top Architect
Diagnosing and Solving a Tomcat Embedded 100 ms Delay Bug in Spring Boot Using Arthas

The author encountered an unexpected ~100 ms overhead in a Spring Boot channel system that forwards requests through Nginx. Direct curl calls to http://127.0.0.1:7744/send showed 73 ms on the first request and only 3 ms on subsequent calls, indicating a one‑time cost.

Initial analysis ruled out business logic, network latency (ping to the Nginx host and the backend server showed sub‑millisecond delays), and local IDE testing could not reproduce the issue, suggesting the problem lies in the runtime environment.

Using the Java diagnostic tool Arthas , the author traced the request flow. A trace org.springframework.web.servlet.DispatcherServlet * command revealed that Spring MVC only consumed ~18 ms, while the remaining ~97 ms were unaccounted for. Further tracing of org.apache.coyote.http11.Http11Processor.service and org.apache.coyote.Adapter.service highlighted a 129 ms hotspot in Tomcat’s request processing.

Deep inspection of the call stack showed repeated invocations of

org.apache.catalina.webresources.TomcatJarInputStream.getNextJarEntry()

, which spent up to 74 ms loading 31 JAR entries. A subsequent

watch org.apache.catalina.webresources.TomcatJarInputStream createZipEntry "{params[0]}"

revealed that the entries were Swagger UI static resources (e.g., META-INF/resources/swagger-ui.html).

Removing the Swagger dependencies ( io.springfox:springfox-swagger2 and io.springfox:springfox-swagger-ui) eliminated the latency, confirming that Tomcat‑embed incorrectly re‑loads these resources on each cold request. The root cause is a bug in Tomcat 8.5.31’s Mapper.internalMapWrapper handling of static resources, which fails to cache them properly; the cache TTL is 5 seconds, so a cold request incurs the full load time.

Solution: upgrade the embedded Tomcat version to 8.5.40 or later (or upgrade Spring Boot to a version that bundles the fixed Tomcat). The upgrade can be done via Maven

<properties><tomcat.version>8.5.40</tomcat.version></properties>

or by moving to Spring Boot 2.1.x+, which already includes a newer Tomcat.

Key takeaways: use Arthas for live method tracing, identify hidden I/O costs in the servlet container, and ensure third‑party static resources do not trigger costly JAR scans in production.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaperformanceSpring BootbugArthasSwagger
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.