You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
NativeBinaryLoader.loadLibrary() fails silently if clean extraction fails #46
try {
loader.loadLibrary(LoadingCriterion.CLEAN_EXTRACTION);
} catch (Exceptionexception) {
thrownewIllegalStateException(
"Failed to load a native library!", exception);
}
If none of the registered native libraries is loadable (for instance because the libraries with matching predicates are missing from the JAR) the code above does not throw an exception. The failure isn't discovered until the application tries to invoke a native method, at which time a UnsatisfiedLinkError is thrown.
I expected an exception to be thrown during loadLibrary(). Ideally diagnostics should indicate:
Perhaps a concrete example will clarify the issue.
I modified TestBasicFeatures.java to report whether loadLibrary() throws an exception:
+++ b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBasicFeatures.java@@ -74,7 +74,14 @@
loader.setRetryWithCleanExtraction(true);
/* Native dynamic library properties */
printDetails(loader);
- loader.loadLibrary(LoadingCriterion.INCREMENTAL_LOADING);
\ No newline at end of file
++ try {+ loader.loadLibrary(LoadingCriterion.INCREMENTAL_LOADING);+ } catch (Exception exception) {+ System.err.println("loadLibrary threw an exception");+ System.exit(-1);+ }+ System.err.println("no exception thrown");
\ No newline at end of file
}
protected static void printDetails(NativeBinaryLoader loader) {
Then I replaced the NativeDynamicLibrary for my platform with an invalid entry:
# This patch file was generated by NetBeans IDE# It uses platform neutral UTF-8 encoding and \n newlines.--- a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBasicFeatures.java+++ b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBasicFeatures.java@@ -58,7 +58,7 @@
public static final NativeDynamicLibrary[] libraries = new NativeDynamicLibrary[] {
DefaultDynamicLibraries.LINUX_X86,
- DefaultDynamicLibraries.LINUX_X86_64,+ new NativeDynamicLibrary("nonexistent/directory", "junk", PlatformPredicate.LINUX_X86_64),
new NativeDynamicLibrary("lib/windows/x86", "libjmealloc.dll", PlatformPredicate.WIN_X86),
new NativeDynamicLibrary("lib/windows/x86-64", "libjmealloc.dll", PlatformPredicate.WIN_X86_64),
DefaultDynamicLibraries.MAC_X86,
When I execute this modified TestBasicFeatures, no exception is thrown.
The file locator system throws these, when a non-existent library is trying to be located:
> Task :snaploader-examples:run
--------------------------------------------------------------
OS: Linux
ARCH: amd64
VM: Java HotSpot(TM) 64-Bit Server VM
--------------------------------------------------------------
Jar Path: /media/pavl-g/pavl-g/Digital-Library/Projects/jSnapLoader/snaploader-examples/libs/jme3-alloc-desktop-1.0.0-pre-gamma-2.jar
Library Directory: nonexistent/directory
Compressed library path: nonexistent/directory/junk
Extracted library absolute path: /media/pavl-g/pavl-g/Digital-Library/Projects/jSnapLoader/snaploader-examples/libs/junk
Is Extracted: false
--------------------------------------------------------------
Oct 04, 2026 2:44:38 PM electrostatic4j.snaploader.library.LibraryExtractor initialize(int)
INFO: File extractor initialized with hash key #1705710286
Oct 04, 2026 2:44:38 PM electrostatic4j.snaploader.library.LibraryLocator close
INFO: File locator #1848380775 resources closed!
Oct 04, 2026 2:44:38 PM electrostatic4j.snaploader.NativeBinaryLoader$2 preInitLibraryLocator
SEVERE: Locating native libraries has failed!
electrostatic4j.snaploader.throwable.FilesystemResourceInitializationException: Cannot locate the file entry in the compression!
at electrostatic4j.snaploader.util.StreamObjectValidator.validateAndThrow(StreamObjectValidator.java:62)
at electrostatic4j.snaploader.filesystem.FileLocator.externalCompressionRoutine(FileLocator.java:179)
at electrostatic4j.snaploader.filesystem.FileLocator.initialize(FileLocator.java:131)
at electrostatic4j.snaploader.NativeBinaryLoader.initializeLibraryExtractor(NativeBinaryLoader.java:457)
at electrostatic4j.snaploader.NativeBinaryLoader.cleanExtractBinary(NativeBinaryLoader.java:379)
at electrostatic4j.snaploader.NativeBinaryLoader.loadLibrary(NativeBinaryLoader.java:196)
at electrostatic4j.snaploader.examples.TestBasicFeatures.main(TestBasicFeatures.java:78)
Oct 04, 2026 2:44:38 PM electrostatic4j.snaploader.library.LibraryExtractor close
INFO: File extractor #1705710286 resources closed!
Oct 04, 2026 2:44:38 PM electrostatic4j.snaploader.NativeBinaryLoader cleanExtractBinary
INFO: File extractor handler initialized!
Oct 04, 2026 2:44:38 PM electrostatic4j.snaploader.NativeBinaryLoader$1 cleanExtractBinary
SEVERE: Extraction has failed!
electrostatic4j.snaploader.throwable.FilesystemResourceInitializationException: Broken file locator stream provider!
at electrostatic4j.snaploader.util.StreamObjectValidator.validateAndThrow(StreamObjectValidator.java:62)
at electrostatic4j.snaploader.filesystem.FileExtractor.extract(FileExtractor.java:138)
at electrostatic4j.snaploader.filesystem.ConcurrentFileExtractor.extract(ConcurrentFileExtractor.java:72)
at electrostatic4j.snaploader.NativeBinaryLoader.cleanExtractBinary(NativeBinaryLoader.java:435)
at electrostatic4j.snaploader.NativeBinaryLoader.loadLibrary(NativeBinaryLoader.java:196)
at electrostatic4j.snaploader.examples.TestBasicFeatures.main(TestBasicFeatures.java:78)
BUILD SUCCESSFUL in 2s
4 actionable tasks: 1 executed, 3 up-to-date
Do you recognize these at your runtime logs?
However, if a broken file already exists; an UnSatisfiedLinkError is thrown because the file is too short (i.e., Corrupted file):
java.lang.UnsatisfiedLinkError: /media/pavl-g/pavl-g/Digital-Library/Projects/jSnapLoader/snaploader-examples/libs/junk: /media/pavl-g/pavl-g/Digital-Library/Projects/jSnapLoader/snaploader-examples/libs/junk: file too short
at java.base/jdk.internal.loader.NativeLibraries.load(Native Method)
at java.base/jdk.internal.loader.NativeLibraries$NativeLibraryImpl.open(NativeLibraries.java:331)
at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:197)
at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:139)
at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2404)
at java.base/java.lang.Runtime.load0(Runtime.java:817)
at java.base/java.lang.System.load(System.java:2015)
at electrostatic4j.snaploader.NativeBinaryLoader.loadBinary(NativeBinaryLoader.java:339)
at electrostatic4j.snaploader.NativeBinaryLoader.loadLibrary(NativeBinaryLoader.java:192)
at electrostatic4j.snaploader.examples.TestBasicFeatures.main(TestBasicFeatures.java:78)
Here's the complete output of "TestBasicFeatures.java" running on Linux with the changes described above:
-------------------------------------------------------------OS: LinuxARCH: amd64VM: OpenJDK 64-Bit Server VM--------------------------------------------------------------Jar Path: /mnt/virginia/home/sgold/NetBeansProjects/ext/jSnapLoader/snaploader-examples/libs/jme3-alloc-desktop-1.0.0-pre-gamma-2.jarLibrary Directory: nonexistent/directoryCompressed library path: nonexistent/directory/junkExtracted library absolute path: /mnt/virginia/home/sgold/NetBeansProjects/ext/jSnapLoader/snaploader-examples/libs/junkIs Extracted: true--------------------------------------------------------------OpenJDK 64-Bit Server VM warning: You have loaded library /mnt/virginia/home/sgold/NetBeansProjects/ext/jSnapLoader/snaploader-examples/libs/junk which might have disabled stack guard. The VM will try to fix the stack guard now.It's highly recommended that you fix the library with 'execstack -c <libfile>', or link it with '-z noexecstack'.Oct 04, 2026 10:22:36 AM electrostatic4j.snaploader.NativeBinaryLoader loadBinarySEVERE: Cannot load the dynamic library: /mnt/virginia/home/sgold/NetBeansProjects/ext/jSnapLoader/snaploader-examples/libs/junkjava.lang.UnsatisfiedLinkError: /mnt/virginia/home/sgold/NetBeansProjects/ext/jSnapLoader/snaploader-examples/libs/junk: /mnt/virginia/home/sgold/NetBeansProjects/ext/jSnapLoader/snaploader-examples/libs/junk: file too short at java.base/jdk.internal.loader.NativeLibraries.load(Native Method) at java.base/jdk.internal.loader.NativeLibraries$NativeLibraryImpl.open(NativeLibraries.java:388) at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:232) at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:174) at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2394) at java.base/java.lang.Runtime.load0(Runtime.java:755) at java.base/java.lang.System.load(System.java:1970) at electrostatic4j.snaploader.NativeBinaryLoader.loadBinary(NativeBinaryLoader.java:339) at electrostatic4j.snaploader.NativeBinaryLoader.loadLibrary(NativeBinaryLoader.java:192) at electrostatic4j.snaploader.examples.TestBasicFeatures.main(TestBasicFeatures.java:79)Oct 04, 2026 10:22:36 AM electrostatic4j.snaploader.library.LibraryExtractor initialize(int)INFO: File extractor initialized with hash key #214123406Oct 04, 2026 10:22:36 AM electrostatic4j.snaploader.library.LibraryLocator closeINFO: File locator #1848380775 resources closed!Oct 04, 2026 10:22:36 AM electrostatic4j.snaploader.NativeBinaryLoader$2 preInitLibraryLocatorSEVERE: Locating native libraries has failed!electrostatic4j.snaploader.throwable.FilesystemResourceInitializationException: Cannot locate the file entry in the compression! at electrostatic4j.snaploader.util.StreamObjectValidator.validateAndThrow(StreamObjectValidator.java:62) at electrostatic4j.snaploader.filesystem.FileLocator.externalCompressionRoutine(FileLocator.java:179) at electrostatic4j.snaploader.filesystem.FileLocator.initialize(FileLocator.java:131) at electrostatic4j.snaploader.NativeBinaryLoader.initializeLibraryExtractor(NativeBinaryLoader.java:457) at electrostatic4j.snaploader.NativeBinaryLoader.cleanExtractBinary(NativeBinaryLoader.java:379) at electrostatic4j.snaploader.NativeBinaryLoader.loadBinary(NativeBinaryLoader.java:366) at electrostatic4j.snaploader.NativeBinaryLoader.loadLibrary(NativeBinaryLoader.java:192) at electrostatic4j.snaploader.examples.TestBasicFeatures.main(TestBasicFeatures.java:79)Oct 04, 2026 10:22:36 AM electrostatic4j.snaploader.library.LibraryExtractor closeINFO: File extractor #214123406 resources closed!Oct 04, 2026 10:22:36 AM electrostatic4j.snaploader.NativeBinaryLoader cleanExtractBinaryINFO: File extractor handler initialized!Oct 04, 2026 10:22:36 AM electrostatic4j.snaploader.NativeBinaryLoader$1 cleanExtractBinarySEVERE: Extraction has failed!electrostatic4j.snaploader.throwable.FilesystemResourceInitializationException: Broken file locator stream provider! at electrostatic4j.snaploader.util.StreamObjectValidator.validateAndThrow(StreamObjectValidator.java:62) at electrostatic4j.snaploader.filesystem.FileExtractor.extract(FileExtractor.java:138) at electrostatic4j.snaploader.filesystem.ConcurrentFileExtractor.extract(ConcurrentFileExtractor.java:72) at electrostatic4j.snaploader.NativeBinaryLoader.cleanExtractBinary(NativeBinaryLoader.java:435) at electrostatic4j.snaploader.NativeBinaryLoader.loadBinary(NativeBinaryLoader.java:366) at electrostatic4j.snaploader.NativeBinaryLoader.loadLibrary(NativeBinaryLoader.java:192) at electrostatic4j.snaploader.examples.TestBasicFeatures.main(TestBasicFeatures.java:79)no exception thrown
How is the application supposed to detect that extraction has failed?
How is the application supposed to detect that extraction has failed?
I've just found the problem and its solution; the problem is that the Java Legacy FileOutputStream creates a new File when it's initialized regardless of whether a physical file pre-existed, which in our case leads to a creation of blank file that is too short or corrupt to be loadable by the dynamic loader.... The result cannot be avoided by jSnapLoader, so the solution is to delete that blank file when the library locator has failed...
The UnSatisfiedLinkError thrown in this case is not as result of trying to invoke a native function, but rather as a result of trying to load a bad file that is not a native binary.
I will submit a PR and let's continue discussion there.
Activity
pavly-gerges commentedon Sep 18, 2026
There is an Exception class dedicated to this:
https://github.com/Electrostat-Lab/jSnapLoader/blob/master/snaploader%2Fsrc%2Fmain%2Fjava%2Felectrostatic4j%2Fsnaploader%2Fthrowable%2FUnSupportedSystemError.java
It might be the case that the caller function misbehaves.
stephengold commentedon Sep 22, 2026
Perhaps a concrete example will clarify the issue.
I modified TestBasicFeatures.java to report whether
loadLibrary()throws an exception:Then I replaced the
NativeDynamicLibraryfor my platform with an invalid entry:When I execute this modified
TestBasicFeatures, no exception is thrown.pavly-gerges commentedon Sep 23, 2026
During the initialization stage; this function should throw an
UnSupportedSystemErrorprior to calling the loading command.jSnapLoader/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java
Lines 126 to 159 in b19346f
Please verify whether the output log has an
UnSupportedSystemError.stephengold commentedon Sep 23, 2026
That error was not thrown because
isSystemFound[0]wastruein line 146.pavly-gerges commentedon Oct 4, 2026
The file locator system throws these, when a non-existent library is trying to be located:
Do you recognize these at your runtime logs?
However, if a broken file already exists; an
UnSatisfiedLinkErroris thrown because the file is too short (i.e., Corrupted file):stephengold commentedon Oct 4, 2026
Here's the complete output of "TestBasicFeatures.java" running on Linux with the changes described above:
How is the application supposed to detect that extraction has failed?
pavly-gerges commentedon Oct 4, 2026
I've just found the problem and its solution; the problem is that the Java Legacy
FileOutputStreamcreates anew Filewhen it's initialized regardless of whether a physical file pre-existed, which in our case leads to a creation of blank file that is too short or corrupt to be loadable by the dynamic loader.... The result cannot be avoided by jSnapLoader, so the solution is to delete that blank file when the library locator has failed...The
UnSatisfiedLinkErrorthrown in this case is not as result of trying to invoke a native function, but rather as a result of trying to load a bad file that is not a native binary.I will submit a PR and let's continue discussion there.