-
Notifications
You must be signed in to change notification settings - Fork 1.7k
native-image: support statically linking JNI libraries #3359
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
Comments
You can do this using Alternatively you can write your own feature for your lib and tell native-image exactly what to do with it: graal/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SecurityServicesFeature.java Lines 245 to 258 in fbab70f
|
Thanks for following up @kristofdho!
(Note, I ran this example inside an ubuntu docker container) Should I not be using |
I'm having troubles getting it to work with The second example does work however. I am on windows btw, so I had to figure out some stuff before I could run your example. In the end, to get it statically linked into the image, I had to add this custom feature to my classpath: import com.oracle.svm.core.annotate.AutomaticFeature;
import com.oracle.svm.core.jdk.NativeLibrarySupport;
import com.oracle.svm.core.jdk.PlatformNativeLibrarySupport;
import com.oracle.svm.hosted.FeatureImpl;
import com.oracle.svm.hosted.c.NativeLibraries;
import org.graalvm.nativeimage.hosted.Feature;
@AutomaticFeature
public class HelloWorldFeature implements Feature {
@Override
public void beforeAnalysis(BeforeAnalysisAccess access) {
NativeLibrarySupport.singleton().preregisterUninitializedBuiltinLibrary("HelloWorld");
PlatformNativeLibrarySupport.singleton().addBuiltinPkgNativePrefix("HelloWorld");
NativeLibraries nativeLibraries = ((FeatureImpl.BeforeAnalysisAccessImpl) access).getNativeLibraries();
nativeLibraries.addStaticJniLibrary("HelloWorld");
}
} For this to compile, you need this dependency: <dependency>
<groupId>org.graalvm.nativeimage</groupId>
<artifactId>svm</artifactId>
<version>21.0.0</version>
<scope>provided</scope>
</dependency> After this, native-image will itself put HelloWorld.lib (since I'm on windows) in the linker command, so all we have to do is make sure the linker can find it, so I had to add In the end, my native-image command looked like this:
The part that is missing when using |
Thanks @kristofdho, that works! Did you mean |
Ah yes, I didn't have a manifest, so I actually used |
Great. I'll go ahead and close this issue. |
Actually, is it possible to put this information in the GraalVM docs somewhere? I understand the user must implement a |
Unfortunately that's not something I can help you with. And strictly speaking, I think those calls are implementation details, and not part of the API. So for an actual API conform solution some code changes and indeed, definitely documentation, would be required. |
Gotcha. In that case, would the original purpose of this issue still be valid? Since there is no stable (or at least a way we would want to document) way to currently do this. |
@olyagpl please check it out |
I published a blog post about this method today, and mentioned the caveat that it's undocumented and unstable. |
An alternative is to build a --shared library and then build your own loader with JNI libraries baked in. That's what I do now. The loader just has to registerNatives() |
@pquiring very interesting. Could you elaborate on how exactly you made it work in your way, step by step? Actually I don't have much experience with JNI, so I don't know what's a loader in this context, how you can build their own loader, how you make EDIT: and does it require having source code for |
My loaders are here: https://github.com/pquiring/javaforce/tree/master/stubs |
For statically linked lib to make This is what I've done in one of my project that using native-image: |
Does it easier to be used in Panama? |
It was an oversight that |
I was able to achieve static linking using a
package com.foo.graal
import com.oracle.svm.core.jdk.PlatformNativeLibrarySupport;
import org.graalvm.nativeimage.hosted.Feature;
public final class JniFeature implements Feature {
@Override
public void beforeAnalysis(BeforeAnalysisAccess access) {
// Treat JNI calls in "com.foo.**" classes as calls to a built-in library.
PlatformNativeLibrarySupport.singleton().addBuiltinPkgNativePrefix("com_foo");
}
}
--add-exports org.graalvm.nativeimage.builder/com.oracle.svm.core.jdk=ALL-UNNAMED
--add-exports org.graalvm.nativeimage.builder/com.oracle.svm.hosted=ALL-UNNAMED
--features=com.foo.graal.JniFeature
|
@nreid260 which GraalVM version did you use to compile your project? I'm using major version
Thanks! |
I was using GraalVM 22. I think you can solve your error by passing more |
native-image
can currently produce static or mostly static executables, except for object files loaded withSystem/loadLibrary
when using JNI. This makes it inconvenient to distribute binaries for applications where the user doesn't have the JNI library present on their system.The only alternative appears to be to build GraalVM from source with library linked, but I would prefer a solution where I could tell
native-image
a list of object files to statically link into the resulting binary.The text was updated successfully, but these errors were encountered: