Skip to content

Fix JDK 25 LinkageError in JavaUnrestrictedClassLoader#6736

Merged
timtebeek merged 1 commit intomainfrom
timtebeek/fix-rpc-receiver-bugs
Feb 13, 2026
Merged

Fix JDK 25 LinkageError in JavaUnrestrictedClassLoader#6736
timtebeek merged 1 commit intomainfrom
timtebeek/fix-rpc-receiver-bugs

Conversation

@timtebeek
Copy link
Copy Markdown
Member

Summary

Fixes a LinkageError that occurs on JDK 25 when parsing projects with Lombok annotations on comment-free main sources followed by test sources containing comments. JDK 25 changed DocCommentTable to reference public API types across module boundaries, causing the app classloader to eagerly load internal compiler classes. This change wraps the defineClass() call in a try-catch for LinkageError and falls back to parent delegation when the class was already loaded.

Test Plan

  • ./gradlew :rewrite-java:test passes
  • No LinkageError when parsing JDK 25 projects with the fix

🤖 Generated with Claude Code

Wrap defineClass() in try-catch for LinkageError to handle JDK 25+ class loader constraint violations. When app classloader eagerly loads com.sun.* classes through cross-module type boundaries, fall back to parent delegation instead of crashing.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
@timtebeek
Copy link
Copy Markdown
Member Author

Verified downstream in rewrite-maven-plugin; as reported we still need to add --add-exports, but can now parse the reproducer provided separately.

@timtebeek
Copy link
Copy Markdown
Member Author

Pinging @shanman190 and @knutwannheden for async review, but I don't see any immediate concerns here.

Copy link
Copy Markdown
Contributor

@shanman190 shanman190 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this looks fine to me.

I wonder if we couldn't check the parent classloader has the entry loaded first prior to loading an entry ourselves. It would avoid the case like this one earlier if we did.

@github-project-automation github-project-automation Bot moved this from In Progress to Ready to Review in OpenRewrite Feb 13, 2026
@timtebeek timtebeek merged commit 07d1ffe into main Feb 13, 2026
1 check passed
@timtebeek timtebeek deleted the timtebeek/fix-rpc-receiver-bugs branch February 13, 2026 17:46
@github-project-automation github-project-automation Bot moved this from Ready to Review to Done in OpenRewrite Feb 13, 2026
mcebanupgrade added a commit to mcebanupgrade/rewrite that referenced this pull request Feb 26, 2026
…assLoader

When running via Maven plugin on JDK 25, the ClassRealm classloader
establishes loader constraints that prevent defineClass for certain
jdk.compiler classes. The existing LinkageError fallback (from openrewrite#6736)
delegates to the parent, but this creates a module split: some classes
end up in the unnamed module while others land in jdk.compiler. Since
jdk.compiler does not export its internal packages to unnamed modules,
cross-references between split classes fail with IllegalAccessError.

Fix by dynamically adding a module export from the named module to the
classloader's unnamed module when falling back to parent delegation.
Uses sun.misc.Unsafe to obtain a trusted MethodHandles.Lookup that can
invoke Module.implAddExports, bypassing the module system's caller check.
All Module API access is done via reflection for Java 8 source compatibility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
sambsnyd pushed a commit that referenced this pull request Feb 28, 2026
…assLoader (#6836)

* Fix JDK 25 IllegalAccessError from module split in JavaUnrestrictedClassLoader

When running via Maven plugin on JDK 25, the ClassRealm classloader
establishes loader constraints that prevent defineClass for certain
jdk.compiler classes. The existing LinkageError fallback (from #6736)
delegates to the parent, but this creates a module split: some classes
end up in the unnamed module while others land in jdk.compiler. Since
jdk.compiler does not export its internal packages to unnamed modules,
cross-references between split classes fail with IllegalAccessError.

Fix by dynamically adding a module export from the named module to the
classloader's unnamed module when falling back to parent delegation.
Uses sun.misc.Unsafe to obtain a trusted MethodHandles.Lookup that can
invoke Module.implAddExports, bypassing the module system's caller check.
All Module API access is done via reflection for Java 8 source compatibility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Run the rewrite-java tests on Java 25 to test fix

* Revert "Run the rewrite-java tests on Java 25 to test fix"

This reverts commit 8393f8d.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Tim te Beek <tim@moderne.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working java java 25+ parser

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

2 participants