Skip to content

Fix slow Lombok initialization caused by ShadowClassLoader scanning entire classpath#7205

Merged
knutwannheden merged 1 commit into
mainfrom
foggy-axolotl
Mar 31, 2026
Merged

Fix slow Lombok initialization caused by ShadowClassLoader scanning entire classpath#7205
knutwannheden merged 1 commit into
mainfrom
foggy-axolotl

Conversation

@knutwannheden

Copy link
Copy Markdown
Contributor

Motivation

When parsing projects that use Lombok on large classpaths (e.g. Moderne CLI), Lombok's ShadowClassLoader spends hundreds of seconds of CPU during LombokProcessor.init(). The ShadowClassLoader.getResources() method calls isPartOfShadowSuffix() on every jar URL from the parent classloader, which opens each jar as a ZipInputStream and sequentially reads every entry to check for lombok-prefixed paths. On a classpath with many large jars, this is extremely slow.

Stack trace from a jstack sample showing the bottleneck (328s CPU / 384s elapsed):

lombok.launch.ShadowClassLoader.isPartOfShadowSuffixJarBased(ShadowClassLoader.java:384)
lombok.launch.ShadowClassLoader.isPartOfShadowSuffix(ShadowClassLoader.java:428)
lombok.launch.ShadowClassLoader.getResources(ShadowClassLoader.java:462)
lombok.core.SpiLoadUtil.findServices(SpiLoadUtil.java:94)
lombok.core.configuration.ConfigurationKeysLoader$LoaderLoader.loadAllConfigurationKeys

Summary

  • Wrap the parent classloader passed to ShadowClassLoader with a ResourceFilteredClassLoader that returns empty results for getResources() / getResource(), while still delegating class loading normally
  • This forces the ShadowClassLoader to rely solely on its override jars (set via shadow.override.lombok), which already contain everything Lombok needs (lombok.jar + rewrite-java-lombok)
  • The change is entirely contained in LombokSupport.java — no parser modifications needed

Test plan

  • rewrite-java-lombok module tests pass
  • rewrite-java-25 Lombok-specific tests pass
  • All 6 modified/dependent modules compile cleanly
  • Verified via jstack that the ShadowClassLoader scanning bottleneck is eliminated — Lombok now proceeds directly to annotation processing

…ntire classpath

Lombok's ShadowClassLoader.getResources() calls isPartOfShadowSuffix() on
every jar URL from the parent classloader, opening each as a ZipInputStream
and reading every entry to check for lombok-prefixed paths. On large
classpaths (e.g. Moderne CLI), this burns hundreds of seconds of CPU.

Wrap the parent classloader with a ResourceFilteredClassLoader that returns
empty results for resource enumeration while still delegating class loading
normally. This forces the ShadowClassLoader to rely solely on its override
jars (set via shadow.override.lombok), which already contain everything
Lombok needs (lombok.jar + rewrite-java-lombok).
@github-project-automation github-project-automation Bot moved this to In Progress in OpenRewrite Mar 30, 2026
@knutwannheden knutwannheden marked this pull request as ready for review March 31, 2026 08:07
@knutwannheden knutwannheden merged commit 7cb3054 into main Mar 31, 2026
1 check passed
@knutwannheden knutwannheden deleted the foggy-axolotl branch March 31, 2026 08:07
@github-project-automation github-project-automation Bot moved this from In Progress to Done in OpenRewrite Mar 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

1 participant