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

    Labels

    status: supersededAn issue that has been superseded by another

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions