UnsatisfiedLinkError With IoUring & GraalVM Native Image
Introduction
In this article, we will explore the issue of UnsatisfiedLinkError
that occurs when running a compiled GraalVM native image that includes netty-transport-native-iouring
. We will delve into the steps to reproduce the issue, the expected behavior, and the environment in which the issue occurs.
Netty Version
The Netty version used in this issue is 4.2.0.RC4.Final
, which includes the netty-transport-native-iouring
module.
GraalVM Version
The GraalVM version used in this issue is 23.0.1 2024-10-15
, which includes the Java(TM) SE Runtime Environment Oracle GraalVM 23.0.1+11.1 (build 23.0.1+11-jvmci-b01)
.
Issue Description
When attempting to run a compiled GraalVM native image that includes netty-transport-native-iouring
, the following error occurs at runtime:
Exception in thread "main" java.lang.UnsatisfiedLinkError: io.netty.channel.uring.Native.ioUringSetup(III)[J [symbol: Java_io_netty_channel_uring_Native_ioUringSetup or Java_io_netty_channel_uring_Native_ioUringSetup__III]
at org.graalvm.nativeimage.builder/com.oracle.svm.core.jni.access.JNINativeLinkage.getOrFindEntryPoint(JNINativeLinkage.java:152)
at org.graalvm.nativeimage.builder/com.oracle.svm.core.jni.JNIGeneratedMethodSupport.nativeCallAddress(JNIGeneratedMethodSupport.java:41)
at io.netty.channel.uring.Native.ioUringSetup(Native Method)
at io.netty.channel.uring.Native.createRingBuffer(Native.java:347)
at io.netty.channel.uring.IoUringIoHandler.<init>(IoUringIoHandler.java:102)
at io.netty.channel.uring.IoUringIoHandler.lambda$newFactory$1(IoUringIoHandler.java:646)
at io.netty.channel.SingleThreadIoEventLoop.<init>(SingleThreadIoEventLoop.java:92)
at io.netty.channel.MultiThreadIoEventLoopGroup.newChild(MultiThreadIoEventLoopGroup.java:207)
at io.netty.channel.MultiThreadIoEventLoopGroup.newChild(MultiThreadIoEventLoopGroup.java:193)
at io.netty.channel.MultiThreadIoEventLoopGroup.newChild(MultiThreadIoEventLoopGroup.java:30)
at io.netty.util.concurrent.MultithreadEventExecutorGroup.<init>(MultithreadEventExecutorGroup.java:84)
at io.netty.util.concurrent.MultithreadEventExecutorGroup.<init>(MultithreadEventExecutorGroup.java:60)
at io.netty.util.concurrent.MultithreadEventExecutorGroup.<init>(MultithreadEventExecutorGroup.java:49)
at io.netty.channel.MultithreadEventLoopGroup.<init>(MultithreadEventLoopGroup.java:59)
at io.netty.channel.MultiThreadIoEventLoopGroup.<init>(MultiThreadIoEventLoopGroup.java:99)
at org.rybar.elis.network.NetworkManager.createEventLoopGroup(NetworkManager.java:59)
at org.rybar.elis.network.NetworkManager.<init>(NetworkManager.java:32)
at org.rybar.elis.MinecraftServer.<clinit>(MinecraftServer.java:39)
at org.rybar.elis.demo.ElisBootstrap.main(ElisBootstrap.java:69)
at java.base@23.0.1/java.lang.invoke.LambdaForm$DMH/sa346b79c.invokeStaticInit(LambdaForm$DMH)
The same code runs correctly when using JVM instead Native Image.
Steps to Reproduce
- Compile a native image using
GraalVM 23.0.1
with a project that includesnetty-transport-native-iouring
. - Run the compiled binary.
- Observe the
UnsatisfiedLinkError
.
Expected Behavior
The application should run without any UnsatisfiedLinkError
, similar to when using a JVM:
java -jar ../build/libs/demo-0.1.0-all.jar
Environment
- OS: Void Linux
- Kernel Version: 6.12.16_1
- GraalVM Version: 23.0.1
- Build Command:
~/.jdks/graalvm-jdk-23.0.1/bin/native-image -cp ../build/libs/demo-*-all.jar org.rybar.elis.demo.ElisBootstrap \
-H:+UnlockExperimentalVMOptions \
-O3 \
-H:ReflectionConfigurationFiles=reflection_config.json \
-H:ResourceConfigurationFiles=resource_config.json
Troubleshooting
To troubleshoot this issue, we can try the following:
- Check the GraalVM version and ensure it is up-to-date.
- Verify that the
netty-transport-native-iouring
module is correctly configured. - Check the native image build command and ensure it is correctly configured.
- Try running the native image with the
-H:+PrintNativeCode
option to print the native code generated by GraalVM. - Check the GraalVM documentation for any known issues or workarounds related to
netty-transport-native-iouring
.
Conclusion
Q: What is an UnsatisfiedLinkError?
A: An UnsatisfiedLinkError is a Java exception that occurs when the Java Virtual Machine (JVM) is unable to find or load a native library (also known as a shared library or DLL) that is required by the Java application.
Q: What is IoUring?
A: IoUring is a Linux-specific I/O multiplexing API that allows for efficient and scalable I/O operations. It is designed to provide a high-performance alternative to traditional I/O APIs such as epoll and kqueue.
Q: What is GraalVM Native Image?
A: GraalVM Native Image is a tool that allows developers to compile Java applications into native executables that can run without the need for a JVM. This can provide significant performance improvements and reduce the memory footprint of the application.
Q: Why do I get an UnsatisfiedLinkError when using IoUring with GraalVM Native Image?
A: The UnsatisfiedLinkError occurs because the native library required by IoUring is not properly loaded by the GraalVM Native Image. This can be due to a variety of reasons, including incorrect configuration, missing dependencies, or issues with the native library itself.
Q: How can I troubleshoot the UnsatisfiedLinkError?
A: To troubleshoot the UnsatisfiedLinkError, you can try the following:
- Check the GraalVM version and ensure it is up-to-date.
- Verify that the IoUring module is correctly configured.
- Check the native image build command and ensure it is correctly configured.
- Try running the native image with the
-H:+PrintNativeCode
option to print the native code generated by GraalVM. - Check the GraalVM documentation for any known issues or workarounds related to IoUring.
Q: Can I use a different I/O API instead of IoUring?
A: Yes, you can use a different I/O API instead of IoUring. However, keep in mind that IoUring is designed to provide high-performance I/O operations, so you may need to consider the performance implications of using a different API.
Q: How can I report an issue with GraalVM Native Image?
A: To report an issue with GraalVM Native Image, you can submit a bug report to the GraalVM issue tracker. Be sure to include as much detail as possible, including the version of GraalVM you are using, the configuration of your native image, and any relevant error messages.
Q: Can I get help with troubleshooting my UnsatisfiedLinkError?
A: Yes, you can get help with troubleshooting your UnsatisfiedLinkError by reaching out to the GraalVM community or seeking assistance from a GraalVM expert.