Skip to content

Avoid parsing nested jar URLs for cached resource lookups #51503

Description

@gregjotau

Spring Boot 4.2.0-SNAPSHOT repeatedly constructs and parses a nested URL in the optimized missing-entry path even when the corresponding nested JarFile is already cached.

In JarUrlConnection.open(URL), a cached nested-JAR lookup currently:

  1. creates a substring for the nested JAR URL;
  2. constructs and parses a URL;
  3. creates a JarFileUrlKey for the cache lookup;
  4. creates a second key for putIfAbsent.

The URL and second key are unnecessary on a cache hit. This is particularly visible when frameworks probe for optional classes or package-info metadata across a large executable JAR.

Controlled benchmark

I benchmarked the exact path against current main at cf5f3b9ea6 using JDK 26 and a 168 MB real application executable JAR. The JMH benchmark prepares 1,024 distinct missing-resource URLs in the same cached nested spring-core JAR and calls URL.openConnection().

Each of ten external pairs alternated baseline/patched order. Every variant ran in a fresh JVM with one fork, two 1-second warmups, four 1-second measurements, -Xms512m -Xmx512m, and the GC profiler.

Variant Average time Allocation
Baseline 283.824 ns/op 615.221 B/op
Direct cached key 145.676 ns/op 279.220 B/op
Change -48.67% -54.61%

All ten pairs favored the change. The paired improvement was 138.148 ns/op with a 99.9% confidence interval of ±25.082 ns/op.

Application JFR confirmation

I also replaced only the affected loader classes in the same application JAR and captured random-port startup JFR recordings with identical settings.

Sample-weighted direct allocation on the targeted path fell from 1,032,112,976 to 204,539,976 bytes (-80.18%). Execution samples whose first frame was a URL constructor fell from 6.10% to 1.03%. This confirms that the isolated allocations are present in a real application startup and that the change removes them.

Six interleaved full-application wall-clock pairs were too noisy to establish an end-to-end duration change: baseline averaged 14.184 seconds and patched averaged 14.157 seconds, with a paired improvement of 0.027 seconds and a 95% confidence interval of ±1.127 seconds. I am including this explicitly to avoid claiming an application startup-time improvement that the wall-clock sample cannot prove.

Proposed change

Create the equivalent JarFileUrlKey directly from the already parsed nested URL specification. Construct and retain a URL only on a cache miss. This preserves the existing key equality rules, including the runtime reference, as well as cold-cache and concurrent-miss behavior.

The loader check passes with 551 tests, zero failures, and three skipped, including new coverage for:

  • direct-key and URL-key equality;
  • runtime-reference isolation;
  • warm and cold cache behavior;
  • deterministic concurrent cache misses;
  • existing nested and non-nested connection behavior.

This does not change NestedJarFile.hasEntry or its locking behavior discussed in #51379. It also retains the DNS-safe JarFileUrlKey semantics introduced for #46015 and #46401.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions