Skip to content

Fix JDK 25 IllegalAccessError from module split in JavaUnrestrictedClassLoader#6836

Merged
sambsnyd merged 3 commits intoopenrewrite:mainfrom
mcebanupgrade:fix/jdk25-module-split-illegal-access
Feb 28, 2026
Merged

Fix JDK 25 IllegalAccessError from module split in JavaUnrestrictedClassLoader#6836
sambsnyd merged 3 commits intoopenrewrite:mainfrom
mcebanupgrade:fix/jdk25-module-split-illegal-access

Conversation

@mcebanupgrade
Copy link
Copy Markdown
Contributor

@mcebanupgrade mcebanupgrade commented Feb 26, 2026

We've encountered this issue with the latest version of the rewrite lib and plugin. I asked Claude Code to analyze, fix and confirm the fix locally and here's the result.
I fully admit that the proposed changes here are beyond my understanding. The details bellow, generated by Claude

Summary

  • On JDK 25, running OpenRewrite via Maven plugin causes IllegalAccessError: class com.sun.tools.javac.parser.JavaTokenizer (in unnamed module) cannot access class com.sun.tools.javac.parser.Tokens$Comment$CommentStyle (in module jdk.compiler) because Maven's ClassRealm establishes loader constraints that force some jdk.compiler classes to fall back to parent delegation, creating a module split
  • The existing LinkageError catch from Fix JDK 25 LinkageError in JavaUnrestrictedClassLoader #6736 correctly falls back to the parent classloader, but the returned class ends up in jdk.compiler module while classes already loaded via defineClass remain in the unnamed module — and jdk.compiler doesn't export its internal packages to unnamed modules
  • Fix adds a dynamic module export from the named module to the classloader's unnamed module when falling back, using sun.misc.Unsafe → trusted MethodHandles.LookupModule.implAddExports (all via reflection for Java 8 source compatibility)

Test plan

  • ./gradlew :rewrite-java:test --tests "org.openrewrite.java.JavaUnrestrictedClassLoaderTest" — 3 tests pass (export mechanism, unnamed module no-op, idempotency)
  • ./gradlew :rewrite-java-25:compatibilityTest --tests "org.openrewrite.java.tree.AnnotationTest" — no regressions
  • Manual: mvn clean -Popenrewrite rewrite:run -Drewrite.activeRecipes=org.openrewrite.java.migrate.UpgradeToJava25 on a real project with JDK 25 — BUILD SUCCESS (previously failed with IllegalAccessError)

🤖 Generated with Claude Code

…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>
@github-project-automation github-project-automation Bot moved this to In Progress in OpenRewrite Feb 26, 2026
@mcebanupgrade mcebanupgrade marked this pull request as ready for review February 26, 2026 17:43
@timtebeek timtebeek self-requested a review February 26, 2026 18:00
@timtebeek timtebeek requested a review from sambsnyd February 26, 2026 21:50
@timtebeek
Copy link
Copy Markdown
Member

Thanks for the help here @mcebanupgrade ! Sam has wrestled with classloaders quite a bit more than I have, so I've tagged him for review.

@timtebeek timtebeek added bug Something isn't working java 25+ parser labels Feb 27, 2026
Copy link
Copy Markdown
Member

@sambsnyd sambsnyd left a comment

Choose a reason for hiding this comment

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

I would like to accept this but the author's lack of confidence gives me pause. Have you tested that this change resolves the issue beyond the provided test? Knowing that this has been validated by more than Claude's assumptions would give me more confidence.

@sambsnyd
Copy link
Copy Markdown
Member

Reading this again I think it looks OK. Seems reasonable to me that this would solve the problem.

@sambsnyd sambsnyd merged commit 6533e0a into openrewrite:main Feb 28, 2026
1 check passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in OpenRewrite Feb 28, 2026
@mcebanupgrade
Copy link
Copy Markdown
Contributor Author

I would like to accept this but the author's lack of confidence gives me pause. Have you tested that this change resolves the issue beyond the provided test? Knowing that this has been validated by more than Claude's assumptions would give me more confidence.

I've tested that this fix indeed fixes my issue - without the fix, the recipe was failing and how it's passing
image
My lack of confidence is mostly about the nature of the changes since I'm not familiar with this API and I also can't say with confidence that this change won't cause some other unwanted side-effects.

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 25+ parser

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

3 participants