Closed greenatatlassian closed 2 years ago
Do you think you could provide a PR that would provide the needed json files ?
Might take me a little while, but I'll try to put one together for you.
Spent some time trying to get this working with graalvm to no success.
I tested with
jansi: 2.3.4
graalvm-ce: 21.2.0
native image executed against: scratch
, gcr.io/distroless/static
For reference, when I ran the graalvm native-image-agent
against a jar using jansi I got the following ouptput.
resource-config.json
{
"resources":{
"includes":[
{"pattern":"\\QMETA-INF/maven/org.fusesource.jansi/jansi/pom.properties\\E"},
{"pattern":"\\Qorg/fusesource/jansi/internal/native/Linux/x86_64/libjansi.so\\E"}
]},
"bundles":[]
}
jni-config.json
[
{
"name":"java.lang.ClassLoader",
"methods":[
{"name":"getPlatformClassLoader","parameterTypes":[] },
{"name":"loadClass","parameterTypes":["java.lang.String"] }
]
},
{
"name":"jdk.internal.loader.ClassLoaders$PlatformClassLoader"
},
{
"name":"org.fusesource.jansi.internal.CLibrary",
"fields":[
{"name":"HAVE_ISATTY"},
{"name":"HAVE_TTYNAME"},
{"name":"TCSADRAIN"},
{"name":"TCSAFLUSH"},
{"name":"TCSANOW"},
{"name":"TIOCGETD"},
{"name":"TIOCGWINSZ"},
{"name":"TIOCSETD"},
{"name":"TIOCSWINSZ"}
]
},
{
"name":"org.graalvm.nativebridge.jni.JNIExceptionWrapperEntryPoints",
"methods":[{"name":"getClassName","parameterTypes":["java.lang.Class"] }]
}
]
When running a graalvm native-image using these configs jansi does not work, with the following error printed.
Failed to load native library:jansi-2.3.4-65da82f66e242fcc-libjansi.so. osinfo: Linux/x86_64
java.lang.UnsatisfiedLinkError: Can't load library: /tmp/jansi-2.3.4-65da82f66e242fcc-libjansi.so
Further information
1.18
works with no error message
2.0
<-> 2.0.1
works, with error message
With https://github.com/fusesource/jansi/commit/2cf446182c823a4c110411b765a1f0367eb8a913, I've been able to compile jansi jar to native using GraalVM CE 21.1.0 and run it successfully on OSX. I haven't had any needs for the delayed initialisation. I'll give it a try on the latest GraalVM to be sure.
@gnodet FYI I'm hitting this with Jansi 2.4.0
and GraalVM 22.2.0
on an ARM Mac:
Jansi 2.4.0
library.jansi.path=
library.jansi.version=
Jansi native library loaded from /var/folders/qd/msrxtq5j1n9fg4bbsw4xgsbh0000gn/T/jansi-2.4.0-f98251e4f71e7e4-libjansi.jnilib
which was auto-extracted from jar:file:/Users/xtaixe/dev/cli/app/target/native-image-source-jar/lib/org.fusesource.jansi.jansi-2.4.0.jar!/org/fusesource/jansi/internal/native/Mac/arm64/libjansi.jnilib
os.name= Mac OS X, os.version= 12.6, os.arch= aarch64
file.encoding= UTF-8
java.version= 17.0.4, java.vendor= Oracle Corporation, java.home= null
jansi.graceful=
jansi.mode=
jansi.out.mode=
jansi.err.mode=
jansi.colors=
jansi.out.colors=
jansi.err.colors=
jansi.passthrough= false
jansi.strip= false
jansi.force= false
jansi.noreset= false
org.fusesource.jansi.Ansi.disable= false
IS_WINDOWS: false
Exception in thread "main" java.lang.UnsatisfiedLinkError: org.fusesource.jansi.internal.CLibrary.isatty(I)I [symbol: Java_org_fusesource_jansi_internal_CLibrary_isatty or Java_org_fusesource_jansi_internal_CLibrary_isatty__I]
at com.oracle.svm.jni.access.JNINativeLinkage.getOrFindEntryPoint(JNINativeLinkage.java:154)
at com.oracle.svm.jni.JNIGeneratedMethodSupport.nativeCallAddress(JNIGeneratedMethodSupport.java:52)
at org.fusesource.jansi.internal.CLibrary.isatty(CLibrary.java)
For now I haven't been able to apply the fix above and if I use --initialize-at-run-time=org.fusesource.jansi.internal.CLibrary
I get Exception in thread "main" java.lang.NoClassDefFoundError: Could not initialize class org.fusesource.jansi.internal.CLibrary
.
I'll report if I find out more.
Ah, using --initialize-at-run-time=org.fusesource.jansi.internal
works.
According to https://medium.com/graalvm/updates-on-class-initialization-in-graalvm-native-image-generation-c61faca461f7, libraries can be shipped with these these command line options in native-image.properties files.
Also, I see CLibrary
does:
static {
LOADED = JansiLoader.initialize();
if (LOADED) {
init();
}
}
If it's possible to move that and other similar initializations to non static blocks, that might also work.
Still getting the same error on CI builds though:
Failed to load native library:jansi-2.4.0-ef27179001bc2f21-libjansi.so. osinfo: Linux/x86_64
java.lang.UnsatisfiedLinkError: Can't load library: /tmp/jansi-2.4.0-ef27179001bc2f21-libjansi.so
Still getting the same error on CI builds though:
Failed to load native library:jansi-2.4.0-ef27179001bc2f21-libjansi.so. osinfo: Linux/x86_64 java.lang.UnsatisfiedLinkError: Can't load library: /tmp/jansi-2.4.0-ef27179001bc2f21-libjansi.so
@xtaixe Any chance you are building a statically linked image in your CI builds? If so, see #246 on why you may be seeing this error.
@rsenden yes, that is correct. I recently discovered this was happening when static linking, but didn't have time to investigate further.
Looks like there was already some work done to address issue #162, but that doesn't seem to quite do everything that was required in my case to get things working with Jansi in a GraalVM native image.
The problem was that native-image build was running the code that finds and links the necessary native library image at build time, so the library was not linked at run time, resulting in an UnsatisfiedLinkError error at runtime:
I was able to overcome this by telling the native image that the relevant classes must be initialised at runtime rather than at build time. I achieved this by adding the following class to my codebase:
It may be possible to add the necessary configuration (either this file, or appropriate
.json
config files) to the Jansi library itself so that it will work correctly "out of the box" with native-image builds on GraalVM. If not, perhaps this will at least be useful to someone else who encounters the same problem.