Fix jansi native library errors on Windows GraalVM native image#34
Fix jansi native library errors on Windows GraalVM native image#34
Conversation
…lVM native image Explicitly add jansi Windows DLL resources to quarkus.native.resources.includes in both kubectl-kport and kport-ide-server application.properties. When running the GraalVM native binary on Windows, CLibrary.<clinit> triggers hawtjni's JansiLoader which tries to extract the embedded jansi.dll from classpath resources. The DLL was missing from the native image binary because the jansi JAR's META-INF/native-image/resource-config.json pattern is not being applied on Windows GraalVM 24 native image builds. By explicitly including the DLL resource paths in quarkus.native.resources.includes, the native image will always embed the Windows DLLs so they can be extracted and loaded at runtime. Agent-Logs-Url: https://github.com/eclipse-jkube/kport/sessions/cc908d9a-d730-4224-b6f2-cbdc3d4fde32 Co-authored-by: sunix <[email protected]>
|
/build-native-windows |
🏁 Native build results✅ Windows: success ➡️ Download artifacts from this Actions run Artifacts expire after 1 day. |
|
@copilot not better |
…esources from jline jline-2.14.6.jar bundles jansi 1.12 with hawtjni-runtime classes shaded inside it. The jline-bundled AnsiConsole (jansi 1.x) is resolved at runtime and uses hawtjni's Library.doLoad() which looks for DLLs at META-INF/native/windows64/ (hawtjni resource format), NOT at org/fusesource/jansi/internal/native/Windows/ (JansiLoader format from standalone jansi 2.x). Previous fix: embedded the wrong (JansiLoader) resource paths This fix: embed the correct (hawtjni) resource paths from jline's bundled jansi Agent-Logs-Url: https://github.com/eclipse-jkube/kport/sessions/494c0309-030f-48a9-8590-673c5bd8b2d7 Co-authored-by: sunix <[email protected]>
... The previous fix was incorrect - it was embedding the wrong resource paths. Root cause: Fixed in dd90461 by changing |
|
/build-native-windows |
🏁 Native build results✅ Windows: success ➡️ Download artifacts from this Actions run Artifacts expire after 1 day. |
|
@copilot interesting, I have something different now |
… on Windows The jansi 1.x DLL (from jline-2.14.6 fat JAR) loads successfully via META-INF/native/windows64/jansi.dll, but its native init() method calls back via JNI (GetStaticFieldID) to set static fields on CLibrary, Kernel32 and their inner classes. GraalVM's JNI layer throws NoSuchFieldError for STDIN_FILENO because those fields are not registered for JNI access. Add jni-config.json to both kubectl-kport and kport-ide-server registering all jansi 1.x internal classes with allDeclaredFields, allDeclaredMethods, and allDeclaredConstructors. Wire up via -H:JNIConfigurationFiles=jni-config.json. Agent-Logs-Url: https://github.com/eclipse-jkube/kport/sessions/4a2c5570-5de8-447e-9f75-041f4665c925 Co-authored-by: sunix <[email protected]>
... Progress! The DLL now loads (resource path fix worked), but the jansi 1.x DLL's Fixed in 55e05d4 by adding |
|
/build-native-windows |
🏁 Native build results✅ Windows: success ➡️ Download artifacts from this Actions run Artifacts expire after 1 day. |
|
/build-native-linux |
🏁 Native build results✅ Linux: success ➡️ Download artifacts from this Actions run Artifacts expire after 1 day. |
On Windows, running
kubectl-kport.exe initcrashes becausejline-2.14.6.jaris a fat/shaded JAR that bundlesjansi 1.12andhawtjni-runtimeinside it. The jline-bundledorg.fusesource.jansi.AnsiConsole(jansi 1.x) class is used at runtime due to classpath resolution order, and itsCLibrary.<clinit>uses hawtjni'sLibrary.doLoad()to load the native library.Root cause
Two issues prevent the native library from initializing correctly in the GraalVM native binary:
Missing DLL resources: hawtjni looks for the Windows DLL at
META-INF/native/windows64/jansi.dllviaClassLoader.getResource(), but this resource fromjline-2.14.6.jaris not embedded in the GraalVM native binary by default.Missing JNI field registrations: Once the DLL loads, its native
init()method calls back via JNI (GetStaticFieldID) to set ~61 static fields onCLibrary,Kernel32, and their inner classes. GraalVM's JNI layer throwsNoSuchFieldError(e.g.CLibrary.STDIN_FILENO) because those fields are not registered for JNI access.Fix
1. Embed the hawtjni-format Windows DLL resources
Add the DLL resource paths to
quarkus.native.resources.includesin both modules:quarkus.native.resources.includes=...,META-INF/native/windows64/jansi.dll,META-INF/native/windows32/jansi.dll2. Register jansi 1.x internal classes for JNI access
Add a
jni-config.jsonto both modules registering allorg.fusesource.jansi.internal.*classes (CLibrary,CLibrary$Termios,CLibrary$WinSize,Kernel32, and allKernel32inner classes) withallDeclaredFields,allDeclaredMethods, andallDeclaredConstructors. Wire it up via:Both
kubectl-kportandkport-ide-serverapplication.propertiesand resources are updated. Including the Windows DLL resources in non-Windows builds is harmless — hawtjni will simply never load the wrong-platform DLL.