Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ClassNotFoundException "com.sun.tools.javac.code.Type$UnknownType" on JDK 24 #118

Open
mkarg opened this issue Dec 9, 2024 · 8 comments
Labels
bug Something isn't working java-24+

Comments

@mkarg
Copy link

mkarg commented Dec 9, 2024

What version of OpenRewrite are you using?

I am using

  • OpenRewrite 2.23.1
  • rewrite-templating 1.19.1

How are you running OpenRewrite?

I wrote a simple demo project to learn writing recipes, it is privately available at https://github.com/mkarg/MyRecipe, but I will invite you (please send Github User ID).

What is the smallest, simplest way to reproduce the problem?

I assume that any template (even an empty one) will fail to compile on JDK 24.

What did you expect to see?

The same as on JDK 21: mvn compile runs successful.

What did you see instead?

On JDK 24 mvn compile says:

        ... 28 more
Caused by: java.lang.NoClassDefFoundError: com/sun/tools/javac/code/Type$UnknownType
        at org.openrewrite.java.isolated.ReloadableJava21TypeMapping.type(ReloadableJava21TypeMapping.java:49)
        at org.openrewrite.java.isolated.ReloadableJava21TypeMapping.type(ReloadableJava21TypeMapping.java:387)
        at org.openrewrite.java.isolated.ReloadableJava21TypeMapping.type(ReloadableJava21TypeMapping.java:380)
        at org.openrewrite.java.isolated.ReloadableJava21ParserVisitor.visitMemberSelect(ReloadableJava21ParserVisitor.java:894)
        at org.openrewrite.java.isolated.ReloadableJava21ParserVisitor.visitMemberSelect(ReloadableJava21ParserVisitor.java:75)
        at com.sun.tools.javac.tree.JCTree$JCFieldAccess.accept(JCTree.java:2585)
        at com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:92)
        at org.openrewrite.java.isolated.ReloadableJava21ParserVisitor.convert(ReloadableJava21ParserVisitor.java:1671)
        ... 26 more
Caused by: java.lang.ClassNotFoundException: com.sun.tools.javac.code.Type$UnknownType
        at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:349)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:557)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:490)
        at org.openrewrite.java.JavaUnrestrictedClassLoader.loadClass(JavaUnrestrictedClassLoader.java:118)
        ... 34 more

What is the full stack trace of any errors you encountered?

I assume this is not needed as the quotation above should be clear enough.

Are you interested in contributing a fix to OpenRewrite?

I do not feel confident with the internals of OpenRewrite, so I think I am not able to proive a fix on my own.

@mkarg mkarg added the bug Something isn't working label Dec 9, 2024
@timtebeek
Copy link
Contributor

Thanks for the early warning here @mkarg ! Linking the offending line here:
https://github.com/openrewrite/rewrite/blob/16df13a793ab49e575759b66e18e6511b2f82ffa/rewrite-java-21/src/main/java/org/openrewrite/java/isolated/ReloadableJava21ParserVisitor.java#L1671

I don't think this is specific to rewrite-templating right? Probably more so for openrewrite/rewrite? Or were you specifically looking to use our annotation processor for Refaster style recipes?

For now we had focused on parsing Java 21 level sources, and did a small adjustment to support Java 23 runtime. Java 24 we'll likely reevaluate closer to the release, and then we'll still have to determine if we'll support that at the source level or only for runtime until Java 25 rolls around.

@timtebeek timtebeek moved this to Backlog in OpenRewrite Dec 9, 2024
@mkarg
Copy link
Author

mkarg commented Dec 9, 2024

@timtebeek Note: I have sent you an invitation for my repo, so you can see the actual demo code.

In fact I am developing a Refaster recipe for Reader.of(CharSequence) introduced in JDK 24.

(Disclaimer: I am the author of that new API in OpenJDK. My intention is to provide a "migrate to JDK 24" recipe ASAP to speed up common adoption of that particular release due to the lots of changes in 24, and to provide similar recipes for each later JDK release (not just LTS). Hence waiting till JDK 25 is definitively not an option, and I would really kindly ask you to support Java 24 on source and runtime levels to not become a showstopper for my further -hopefull sustaining- contribution to OpenRewrite. Also kindly asking to start work on JDK 24 support ASAP as there is no difference between the current 24 EA builds and later builds, other than bug fixes. There is no benefit in waiting, there won't be any changes! Thanks.)

/cc @MBoegers

@timtebeek
Copy link
Contributor

Good to have that reasoning covered here as well @mkarg ; thanks!

Perhaps good to note here is that Refaster-style recipes are just one of three ways we have to write recipes, and are the only one that requires the target classes to be on the classpath. So while Refaster recipes are certainly the most convenient to express this change, for the goal of allowing folks to upgrade to Java 24 and adopt this pattern one could also write a regular imperative recipe.

Our imperative recipes (including for instance the Java 21+ SequencedCollection recipes) are able to run from Java 8 onwards, allowing folks running an older version of Java still to be able to build their project with the version it requires, to pull that up to whichever version they want to be on. We even go so far as to have our RefasterTemplateProcessor produce Java 8 compatible code, even for newer language constructs, as used by the folks at error-prone-support to generate Java 8 compatible recipes for Java 17 constructs.

Java 24 parser and runtime support would then only be necessary for classes that use features uniquely available in Java 24+, or recipe modules compiled with Java 24 without the target level set back to 8.

Perhaps that gives you some peace of mind that the path for recipes to upgrade to Java 24 is not at all dependent on a parser for Java 24. So while we'd love to support Java 24 soon, we feel there's less urgency for now, and would have to balance this against other requests leveraged our way. I hope that context from our end helps! Any help of course is appreciated. :)

@mkarg
Copy link
Author

mkarg commented Dec 10, 2024

Thank you Tim. I understand that you want me to author an imperative recipe instead of a refaster recipe. So I will do that. Nevertheless, independend of my personal case, Team OpenJDK in general would be happy if all tools and libs adopt JDK 24-EA ASAP and do not wait for JDK24-GA or JDK 25-LTS.

@timtebeek
Copy link
Contributor

An imperative recipe indeed would help ensure your recipe is able to run from older Java versions, for folks inclined to go from something very old to latest. If you take your ReplaceStringReader recipe and compile that on Java 23, you should already find it generates a ReplaceStringReaderRecipe class that you can use (once you remove the second @AfterTemplate annotated method) . That generated recipe can serve as a basis for your imperative recipe. You're welcome to contribute that to rewrite-migrate-java if you're looking to collaborate on the recipe and make it easily available to others.

@mkarg
Copy link
Author

mkarg commented Dec 10, 2024

An imperative recipe indeed would help ensure your recipe is able to run from older Java versions, for folks inclined to go from something very old to latest. If you take your ReplaceStringReader recipe and compile that on Java 23, you should already find it generates a ReplaceStringReaderRecipe class that you can use (once you remove the second @AfterTemplate annotated method) . That generated recipe can serve as a basis for your imperative recipe. You're welcome to contribute that to rewrite-migrate-java if you're looking to collaborate on the recipe and make it easily available to others.

Already did exactly that (and yes, contribution to rewrite-migra-java is the mid-term goal, as I am not a user of OpenRewrite myself, but doing this for the community solely), but now I am stuck with the next problem: How to apply ChangeType to solely the data flow of the actual changed expression's resuslt (i. e. to keep the original type in general, but replace solely the actual "downstream use" of the changed expression's result? 🤔

@timtebeek
Copy link
Contributor

To evaluate downstream usage you might want to look at the work done for the Joda-Time to JDK migrations here:
https://github.com/openrewrite/rewrite-migrate-java/tree/main/src/main/java/org/openrewrite/java/migrate/joda

As to the JDK 24 ClassNotFoundException you'll want to follow this issue, which has some hints towards support as well

@mkarg
Copy link
Author

mkarg commented Dec 11, 2024

Thank you for the link to Joda-Time. In fact, I need to say that this looks all way too complex for such a simple and rather common refactoring like "Replace Expression-A by Expression-B, then ensure that downstream flow uses B instead of A". I am sorry to say but I see the need for such masses of code for such a simple recipe being a major obstacle for my further contribution attempts. Is there any chance that some time soon the OpenRewrite team would come up with more reusable atom utilities for this, in the sense of replaceExpressionAndCorrectDownstreamResultType(cursor, oldExpression, newExpression)? 🤔 There already are things like maybeAddImport, which is great, and which is the level that is needed to exist for people to provide recipes.

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-24+
Projects
Status: Backlog
Development

No branches or pull requests

2 participants