[GR-51123] Native image fails to load a DLL from a path that contains non-ASCII characters
Native image fails to load a DLL from a path that contains non-ASCII characters... or from a path that contains the ~N tilde notation.
Describe the issue
This is a Windows only issue.
I have an app that uses JNA. JNA initially loads a DLL (jnidispatch.dll) after extracting it into a temporary folder that looks like this: C:\Users\<username>\AppData\Local\Temp\jna--187459531\jna11031635164979162837.dll
If the <username> contains non-ASCII characters (e.g. José), or if, in addition to containing non-ASCII characters, the username is too long (Alejandría) and Windows uses the ~N tilde notation (C:\Users\Alejan~1\AppData\...), the GraalVM native image fails loading the DLL:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Can't load library: C:\Users\Alejan~1\AppData\Local\Temp\jna--187459531\jna11031635164979162837.dll
at org.graalvm.nativeimage.builder/com.oracle.svm.core.jdk.NativeLibrarySupport.loadLibraryAbsolute(NativeLibrarySupport.java:100)
at [email protected]/java.lang.ClassLoader.loadLibrary(ClassLoader.java:114)
at [email protected]/java.lang.Runtime.load0(Runtime.java:852)
at [email protected]/java.lang.System.load(System.java:2021)
at com.sun.jna.Native.loadNativeDispatchLibraryFromClasspath(Native.java:1045)
at com.sun.jna.Native.loadNativeDispatchLibrary(Native.java:1015)
at com.sun.jna.Native.<clinit>(Native.java:221)
at mousemaster.ExtendedKernel32.<clinit>(ExtendedKernel32.java:7)
Steps to reproduce the issue
To reproduce that problem, I just had to give JNA (-Djna.tmpdir) a path containing the ~N tilde notation.
- mkdir C:\Alejandría
- cd C:\Alejandría
- git clone https://github.com/petoncle/mousemaster .
- mvnw clean package
- mvnw -Pnative -Dagent package
- mv target\mousemaster.exe .
- mousemaster.exe -Djna.debug_load=true -Djna.tmpdir=C:\Alejan~1
Describe GraalVM and your environment:
- GraalVM version: graalvm-jdk-21.0.1+12.1
- JDK major version: 21
- OS: Windows 10 and 11
- Architecture: x86-64
More details
This works (non-native version running with graalvm-jdk-21.0.1+12.1):
C:\Alejandría>C:\graalvm-jdk-21.0.1+12.1\bin\java -Djna.debug_load=true -Djna.tmpdir=C:\Alejan~1 -jar mousemaster.jar
INFO: Found library resource at jar:file:/C:/Alejandr%c3%ada/mousemaster.jar!/com/sun/jna/win32-x86-64/jnidispatch.dll
Dec 26, 2023 4:23:13 PM com.sun.jna.Native extractFromResourcePath
INFO: Extracting library to C:\Alejan~1\jna2218230710365587904.dll
Dec 26, 2023 4:23:13 PM com.sun.jna.NativeLibrary loadLibrary
(...)
This does not work (native image):
C:\Alejandría>mousemaster.exe -Djna.debug_load=true -Djna.tmpdir=C:\Alejan~1
INFO: Found library resource at resource:/com/sun/jna/win32-x86-64/jnidispatch.dll
Dec 26, 2023 4:26:17 PM com.sun.jna.Native extractFromResourcePath
INFO: Extracting library to C:\Alejan~1\jna18325864350615041260.dll
Exception in thread "main" java.lang.UnsatisfiedLinkError: Can't load library: C:\Alejan~1\jna18325864350615041260.dll
at org.graalvm.nativeimage.builder/com.oracle.svm.core.jdk.NativeLibrarySupport.loadLibraryAbsolute(NativeLibrarySupport.java:100)
(...)
This works (native image still, ~N tilde notation still, but only ASCII characters: Alejandro):
C:\Alejandro>mousemaster.exe -Djna.debug_load=true -Djna.tmpdir=C:\Alejan~1
INFO: Found library resource at resource:/com/sun/jna/win32-x86-64/jnidispatch.dll
Dec 26, 2023 4:33:13 PM com.sun.jna.Native extractFromResourcePath
INFO: Extracting library to C:\Alejan~1\jna10184328519890257310.dll
Dec 26, 2023 4:33:13 PM com.sun.jna.NativeLibrary loadLibrary
(...)
Thanks For reporting, we are tracking it internally.
Any updates on this? this is a serious problem
As a temporary workaround, you can set -J-Dsun.jnu.encoding=Cp1252 during native image build.
Thanks for looking into this @antonwiens. I've tried to add -J-Dsun.jnu.encoding=Cp1252 to my native-image.properties:
Args=-H:+AddAllCharsets -march=compatibility -J-Dsun.jnu.encoding=Cp1252
then built the native image:
JAVA_HOME=~/Documents/tools/graalvm-jdk-21.0.1+12.1/ ./mvnw -Pnative -Dagent package
but the DLL still could not be loaded:
c:\Alejandría>mousemaster.exe -Djna.debug_load=true -Djna.tmpdir=C:\Alejandría
2025-05-22T11:13:23.390 [main] INFO com.sun.jna.Native - Looking in classpath from jdk.internal.loader.ClassLoaders$AppClassLoader@34ce8af7 for /com/sun/jna/win32-x86-64/jnidispatch.dll
2025-05-22T11:13:23.390 [main] INFO com.sun.jna.Native - Found library resource at resource:/com/sun/jna/win32-x86-64/jnidispatch.dll
2025-05-22T11:13:23.397 [main] INFO com.sun.jna.Native - Extracting library to C:\Alejandr�a\jna16178858372183860130.dll
Exception in thread "main" java.lang.UnsatisfiedLinkError: Can't load library: C:\Alejandr�a\jna16178858372183860130.dll
at org.graalvm.nativeimage.builder/com.oracle.svm.core.jdk.NativeLibrarySupport.loadLibraryAbsolute(NativeLibrarySupport.java:100)
at [email protected]/java.lang.ClassLoader.loadLibrary(ClassLoader.java:114)
at [email protected]/java.lang.Runtime.load0(Runtime.java:852)
at [email protected]/java.lang.System.load(System.java:2021)
at com.sun.jna.Native.loadNativeDispatchLibraryFromClasspath(Native.java:1045)
at com.sun.jna.Native.loadNativeDispatchLibrary(Native.java:1015)
at com.sun.jna.Native.<clinit>(Native.java:221)
at mousemaster.ExtendedKernel32.<clinit>(ExtendedKernel32.java:8)
at mousemaster.WindowsClock.<clinit>(WindowsClock.java:10)
at mousemaster.WindowsPlatform.<init>(WindowsPlatform.java:22)
at mousemaster.MousemasterApplication.platform(MousemasterApplication.java:139)
at mousemaster.MousemasterApplication.main(MousemasterApplication.java:104)
at [email protected]/java.lang.invoke.LambdaForm$DMH/sa346b79c.invokeStaticInit(LambdaForm$DMH)
Is there anything I'm doing wrong here?
Sorry, i forgot to mention that you also need file encoding and native encoding -J-Dfile.encoding=Cp1252 -J-Dnative.encoding=Cp1252 -J-Dsun.jnu.encoding=Cp1252
Just tested it to be sure. At least it works for me with umlauts like öäü.
Awesome, that works for me too (even though the folder name shows up incorrectly when printed in the console: C:\Alejandrφa instead of C:\Alejandría):
Args=-H:+AddAllCharsets -march=compatibility -J-Dfile.encoding=Cp1252 -J-Dnative.encoding=Cp1252 -J-Dsun.jnu.encoding=Cp1252
C:\Alejandría>mousemaster.exe -Djna.debug_load=true -Djna.tmpdir=C:\Alejandría
2025-05-23T05:42:18.318 [main] INFO com.sun.jna.Native - Looking in classpath from jdk.internal.loader.ClassLoaders$AppClassLoader@34ce8af7 for /com/sun/jna/win32-x86-64/jnidispatch.dll
2025-05-23T05:42:18.318 [main] INFO com.sun.jna.Native - Found library resource at resource:/com/sun/jna/win32-x86-64/jnidispatch.dll
### Not sure why the next log shows Alejandrφa instead of Alejandría.
### But it's able to load the DLL anyway
### and the DLL is in C:\Alejandría (not C:\Alejandrφa).
2025-05-23T05:42:18.324 [main] INFO com.sun.jna.Native - Extracting library to C:\Alejandrφa\jna615909175248744833.dll
I wonder why it's not working when I change Cp1252 to UTF-8:
Args=-H:+AddAllCharsets -march=compatibility -J-Dfile.encoding=UTF-8 -J-Dnative.encoding=UTF-8 -J-Dsun.jnu.encoding=UTF-8
C:\Alejandría>mousemaster.exe -Djna.debug_load=true -Djna.tmpdir=C:\Alejandría
2025-05-23T05:36:48.200 [main] INFO com.sun.jna.Native - Looking in classpath from jdk.internal.loader.ClassLoaders$AppClassLoader@34ce8af7 for /com/sun/jna/win32-x86-64/jnidispatch.dll
2025-05-23T05:36:48.200 [main] INFO com.sun.jna.Native - Found library resource at resource:/com/sun/jna/win32-x86-64/jnidispatch.dll
2025-05-23T05:36:48.207 [main] INFO com.sun.jna.Native - Extracting library to C:\Alejandr�a\jna14709197415953247159.dll
Exception in thread "main" java.lang.UnsatisfiedLinkError: Can't load library: C:\Alejandr�a\jna14709197415953247159.dll
at org.graalvm.nativeimage.builder/com.oracle.svm.core.jdk.NativeLibrarySupport.loadLibraryAbsolute(NativeLibrarySupport.java:100)
(I would have liked to make it work with non-Latin characters like C:\こんにちは.)
I also noticed that the console output is always wrong, with utf-8 or cp1252. Did you try it with non-latin characters and it doesnt work?
Btw. setting to utf-8 doesnt work because i think that is the default
I also noticed that the console output is always wrong, with utf-8 or cp1252. Did you try it with non-latin characters and it doesnt work?
This is what I get with non-latin characters:
C:\こんにちは>mousemaster.exe -Djna.debug_load=true -Djna.tmpdir=C:\こんにちは
2025-05-23T06:01:43.042 [main] WARN com.sun.jna.Native - JNA Warning: IOException removing temporary files
java.io.IOException: JNA temporary directory 'C:\?????' does not exist
at com.sun.jna.Native.getTempDir(Native.java:1357)
at com.sun.jna.Native.removeTemporaryFiles(Native.java:1367)
at com.sun.jna.Native.loadNativeDispatchLibrary(Native.java:946)
at com.sun.jna.Native.<clinit>(Native.java:221)
at mousemaster.ExtendedKernel32.<clinit>(ExtendedKernel32.java:8)
at mousemaster.WindowsClock.<clinit>(WindowsClock.java:10)
at mousemaster.WindowsPlatform.<init>(WindowsPlatform.java:22)
at mousemaster.MousemasterApplication.platform(MousemasterApplication.java:139)
at mousemaster.MousemasterApplication.main(MousemasterApplication.java:104)
at [email protected]/java.lang.invoke.LambdaForm$DMH/sa346b79c.invokeStaticInit(LambdaForm$DMH)
2025-05-23T06:01:43.043 [main] INFO com.sun.jna.Native - Looking in classpath from jdk.internal.loader.ClassLoaders$AppClassLoader@34ce8af7 for /com/sun/jna/win32-x86-64/jnidispatch.dll
2025-05-23T06:01:43.045 [main] INFO com.sun.jna.Native - Found library resource at resource:/com/sun/jna/win32-x86-64/jnidispatch.dll
Exception in thread "main" java.lang.UnsatisfiedLinkError: Failed to create temporary file for /com/sun/jna/win32-x86-64/jnidispatch.dll library: JNA temporary directory 'C:\?????' does not exist
at com.sun.jna.Native.loadNativeDispatchLibraryFromClasspath(Native.java:1059)
at com.sun.jna.Native.loadNativeDispatchLibrary(Native.java:1015)
at com.sun.jna.Native.<clinit>(Native.java:221)
at mousemaster.ExtendedKernel32.<clinit>(ExtendedKernel32.java:8)
at mousemaster.WindowsClock.<clinit>(WindowsClock.java:10)
at mousemaster.WindowsPlatform.<init>(WindowsPlatform.java:22)
at mousemaster.MousemasterApplication.platform(MousemasterApplication.java:139)
at mousemaster.MousemasterApplication.main(MousemasterApplication.java:104)
at [email protected]/java.lang.invoke.LambdaForm$DMH/sa346b79c.invokeStaticInit(LambdaForm$DMH)
Btw. setting to utf-8 doesnt work because this is the default
Oh right that makes sense.
However change file.encoding may have impact to application logic. If not handled properly, some strange characters will be stored.
It will be ideal if GraalVM can handle it without touch those properties.