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

LambdaFetchingSupport is broken for cross class loader method access after JDK >= 14 #3369

Open
jord1e opened this issue Oct 27, 2023 · 2 comments
Labels
keep-open Tells Stale Bot to keep PRs and issues open

Comments

@jord1e
Copy link
Contributor

jord1e commented Oct 27, 2023

Describe the bug
Whilst working on #2789 I found this bug.

Java changed the way MethodHandles.privateLookupIn behaves in JDK 14 (?):
A new Lookup::hasFullPrivilegeAccess method for testing full privilege access

This effectively breaks LambdaFetchingSupport.createGetter in cross class loader situations and always silently goes into the try (... ignore) {} and falls back to the original reflection:

Image of the debugger

To Reproduce
Run the LambdaFetchingSupportTest.'different class loaders induce certain behaviours' on a JDK 14+ (triggered for me on JDK 17)

How to fix

Jackson fixed this by (if I understand correctly) creating a dummy class in the same package as the 'hidden' class that has a static reference to the MethodHandle.Lookup instance, which can then be resolved using reflection:

https://github.com/FasterXML/jackson-modules-base/pull/162/files#diff-e2b60292366182a59ba6f53b823219367d18eb1de225ecaf783ea7c7f70b04b2R94

To fix this for GraphQL Java the GrantAccess.java would need to be edited a bit to give the "dummy" class a different name i.e, GraphQLJavaAccess, running this will create the necessary class bytes

Then the CrossLoaderAccess would be copied and the bytes would be modified with the correct class bytes that were generated.

Then the class would have to be "opened up" in LambdaFetchingSupport.getLookup (see CrossLoaderAccess.apply) after which it will work like normal again

Other
I am unsure of how many deployments this applies to, but considering that having GraphQL Java in one class loader and the target classes in another is not the craziest idea, it should probably be fixed. Especially considering the performance gains (#2985 )

It probably wasn't noticed because the tests have not been run JDK>11 because of Gradle toolchains: 091710c#diff-335d1791aad84b00e8762546a158726200525fa06a55b73d8284ff0fea4ac7deR186

#2789 would of course fix this by testing on newer releases

This was also implemented in OpenJ9: eclipse-openj9/openj9#8571
After JDK 17 some things might again be slightly different: https://bugs.openjdk.org/browse/JDK-8221255
Email chain from Jackson Blackbird to lib-core-devs: https://www.mail-archive.com/core-libs-dev@openjdk.java.net/msg83157.html

@bbakerman
Copy link
Member

The good news here is that it falls back to the previous reflection and this decision is remembered between calls.

So while its not as fast as it could be - its not broken per se and it falls back to a secondary strategy. I saw this because before it did not do that and when it broken with funky class loaders we had bad bug

@jord1e
Copy link
Contributor Author

jord1e commented Oct 30, 2023

Yes, it does indeed fall back to the “old” reflection fetcher. And at least Jackson already constructed a fix

would there be interest in a PR from me or will you guys fix it?

@dondonz dondonz added the keep-open Tells Stale Bot to keep PRs and issues open label Dec 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
keep-open Tells Stale Bot to keep PRs and issues open
Projects
None yet
Development

No branches or pull requests

4 participants
@bbakerman @dondonz @jord1e and others