Skip to content

Shadowing Graal as library with relocation fails due to native bindings #10907

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

Open
rubensworks opened this issue Mar 23, 2025 · 10 comments
Open
Assignees

Comments

@rubensworks
Copy link

Describe the issue

I am using GraalVM + GraalJS in a project (a Minecraft mod) in which I must shadow (+relocate, e.g. 'org.graalvm' to 'org.cyclops.integratedscripting.vendors.org.graalvm') these libraries. (shadow+relocate is needed for players using Graal as their JRE)
When updating from Graal 22.3.2 to 24.2.0, I am not able to relocate the com.oracle.truffle.polyglot package anymore due to the native bindings that have been introduced in the JDKSupport class.
As a workaround, I exclude the com.oracle.truffle.polyglot package from relocation when building.
This is unfortunately causing conflicts with other similar projects (Minecraft mods) that are shadowing GraalVM + GraalJS in a similar manner (CyclopsMC/IntegratedScripting#34).

Does anyone here know a way to work around this problem?
Ideally, I'd want to relocate com.oracle.truffle.polyglot as well, but, AFAIK, relocation of native bindings is not possible.

One alternative solution I see is to inject a package prefix for native bindings, similar to the io.netty.packagePrefix in netty. But I could not find such functionality here based on some searching.

Steps to reproduce the issue

Reproduction is a bit complicated, so I would not recommend trying, but I could provide steps upon request.

Describe GraalVM and your environment:

  • GraalVM version (latest snapshot builds can be found here), or commit id if built from source: CE 24.2.0
  • JDK major version: 23
  • OS: macOS Sequoia
  • Architecture: AMD64

Additional Context

This is the shadow config (with excluded relocation) I am using:
https://github.com/CyclopsMC/IntegratedScripting/blob/master-1.21-lts/build.gradle#L260-L272

@chumer
Copy link
Member

chumer commented Mar 25, 2025

Relocation is not tested and not supported on our end. That it worked for you in previous versions was luck.

We can add a test for this and fix potential issues in the future, but you need to provide a reproducer for us that we can integrate in our CI.
Note that the optimizing Truffle runtime cannot work with relocated packages.

@rubensworks
Copy link
Author

Thanks for the reply @chumer.
So if I understand correctly, relocation is not officially supported, but you are open to supporting it?
I will look into creating an MRE with shading+relocation.

@chumer
Copy link
Member

chumer commented Mar 25, 2025

I cannot promise it. It depends on what the problems are that we will see.
And as mentioned native-image compilation or using an optimizing runtime certainly cannot be easily supported.
I would strongly recommend to find a different way of isolation. Maybe a class loader?

@rubensworks
Copy link
Author

As promised, here is the minimal reproducible example: https://github.com/rubensworks/graal-shadow-relocation-mre

I'm happy to help moving this forward any way I can.

@chumer
Copy link
Member

chumer commented Apr 7, 2025

As you can see from the error its failing in JNI bindings which require a stable class name.
I don't see what we should do about that other than swallowing that error and trying to continue anyway.

You say fallback runtime is enough? So bad performance is ok?

@rubensworks
Copy link
Author

I don't see what we should do about that other than swallowing that error and trying to continue anyway.

One option could be to make the JNI method registration dynamic, and allow a package prefix to be set somehow. This is what they did in netty a while ago, to solve similar issues (netty/netty#4800): Scottmitch/netty@47ae721
Would something like this be an option here?

You say fallback runtime is enough? So bad performance is ok?

I think the current explicit error is fine. A fallback with bad performance might be more annoying for users to debug, unless a warning is emitted somehow.

@chumer
Copy link
Member

chumer commented Apr 7, 2025

they did in netty a while ago, to solve similar issues (netty/netty#4800): Scottmitch/netty@47ae721
Would something like this be an option here?

We can look into that. Thanks for the suggestion.

I think the current explicit error is fine. A fallback with bad performance might be more annoying for users to debug, unless a warning is emitted somehow.

Whatever we do we cannot change package names for the optimizing runtime, we currently can attach only one optimizing runtime for Java VM. So your language will always run with the fallback runtime and in interpreted-only mode.
What do you mean by explicit error and warning? I don't think I can follow what you mean.

@rubensworks
Copy link
Author

We can look into that. Thanks for the suggestion.

Great! Do let me know if there's any way I can be of assistance.

What do you mean by explicit error and warning? I don't think I can follow what you mean.

Maybe I'm misunderstanding things.
But I was under the impression that the current JNI bindings crash is because of the optimizing runtime that could not be loaded.
If that's the case, having this explicit crash might be good to keep (if no Netty-like workaround is possible).
Otherwise, if the crash is swallowed and silenced, users may experience slowdowns due to the optimizing runtime not being available, without explicitly opting out of using the optimizing runtime.

@chumer
Copy link
Member

chumer commented Apr 7, 2025

But I was under the impression that the current JNI bindings crash is because of the optimizing runtime that could not be loaded.

The current crash is for some other use of JNI that relates to all runtimes, which might be fixable.
Renaming the package of the optimizing runtime or loading the optimizing runtime multiple times is something that is much harder to do and that we might never be able to support.

Otherwise, if the crash is swallowed and silenced, users may experience slowdowns due to the optimizing runtime not being available, without explicitly opting out of using the optimizing runtime.

We do print a warning by default if the optimizing runtime could not be used and we switch to the fallback runtime. So the consistent thing to do would be to gracefully handle the case (we can detect it by checking for the package name).

@rubensworks
Copy link
Author

Ok, got it, thanks for the clarification @chumer!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants