From 7b0845d43d690751822d42f5b84e1f20c6bdab3f Mon Sep 17 00:00:00 2001 From: pavl-g Date: Sun, 4 Oct 2026 20:53:22 +0300 Subject: [PATCH 01/15] FileExtractor: introduced a file instance; deletes a blank physical file on-failure --- .../snaploader/filesystem/FileExtractor.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileExtractor.java b/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileExtractor.java index db394bb..6d7788f 100644 --- a/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileExtractor.java +++ b/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileExtractor.java @@ -66,6 +66,8 @@ public class FileExtractor implements OutputStreamProvider { */ protected String destination; + protected File extractableFile; + private static final int EOF = -1; /* End-of-filesystem */ /** @@ -103,6 +105,7 @@ public void initialize(int size) throws Exception { return; } this.fileOutputStream = new FileOutputStream(destination); + extractableFile = new File(destination); SnapLoaderLogger.log(Level.INFO, getClass().getName(), "initialize(int)", "File extractor initialized with hash key #" + getHashKey()); } catch (Exception e) { @@ -149,6 +152,14 @@ public void extract() throws IOException, FileNotFoundException { fileExtractionListener.onExtractionCompleted(this); } } catch (Exception e) { + // ensure deleting the blank created files + // by the Java Legacy FileOutputStream upon failure! + + // blank created files; create an opaque behavior + // that triggers an UnSatisfiedLinkError: file is too short + // as a result of trying to load corrupted files + // on the next runtime... + delete(); if (fileExtractionListener != null) { fileExtractionListener.onExtractionFailure(this, e); } @@ -160,6 +171,20 @@ public void extract() throws IOException, FileNotFoundException { } } + /** + * Deletes the associated file created by the Legacy + * Java OutputStream {@link FileExtractor#getFileOutputStream()}. + * + * @return true if the file has been deleted, false otherwise if the + * file is not defined or doesn't exist. + */ + protected boolean delete() { + if (extractableFile == null || !extractableFile.exists()) { + return false; + } + return extractableFile.delete(); + } + @Override public void close() throws Exception { if (fileOutputStream != null) { From 9d53202c62025117bf4104d9fb06b5a3a8210e34 Mon Sep 17 00:00:00 2001 From: pavl-g Date: Sun, 4 Oct 2026 20:54:45 +0300 Subject: [PATCH 02/15] NativeBinaryLoader: enabled the natural flow of retry-with-clean-extraction for the incremental loading criterion --- .../java/electrostatic4j/snaploader/NativeBinaryLoader.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java b/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java index 1731998..292ccc3 100644 --- a/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java +++ b/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java @@ -183,12 +183,13 @@ public NativeBinaryLoader loadLibrary(LoadingCriterion criterion) throws Excepti throw new IllegalArgumentException("Native library data structures cannot be null!"); } // commands and loads the library from the system directories - if (NativeVariant.Os.isAndroid() || criterion == LoadingCriterion.SYSTEM_LOAD) { + if (NativeVariant.Os.isAndroid() || + criterion == LoadingCriterion.SYSTEM_LOAD) { loadSystemBinary(nativeDynamicLibrary); loadingCriterion = LoadingCriterion.SYSTEM_LOAD; return this; } - if (criterion == LoadingCriterion.INCREMENTAL_LOADING && nativeDynamicLibrary.isExtracted()) { + if (criterion == LoadingCriterion.INCREMENTAL_LOADING) { loadBinary(nativeDynamicLibrary, criterion); loadingCriterion = LoadingCriterion.INCREMENTAL_LOADING; return this; From cd04c38d5654470681f79c88d5196fe9d356b3c5 Mon Sep 17 00:00:00 2001 From: pavl-g Date: Sun, 4 Oct 2026 20:55:23 +0300 Subject: [PATCH 03/15] snaploader-examples: introduced a standard way to deal with broken files --- .../examples/TestBrokenFeatures.java | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBrokenFeatures.java diff --git a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBrokenFeatures.java b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBrokenFeatures.java new file mode 100644 index 0000000..f9b1d9a --- /dev/null +++ b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBrokenFeatures.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2023-2024, The Electrostatic-Sandbox Distributed Simulation Framework, jSnapLoader + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'AvrSandbox' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package electrostatic4j.snaploader.examples; + +import electrostatic4j.snaploader.LibraryInfo; +import electrostatic4j.snaploader.NativeBinaryLoader; +import electrostatic4j.snaploader.filesystem.DirectoryPath; +import electrostatic4j.snaploader.filesystem.FileExtractionListener; +import electrostatic4j.snaploader.filesystem.FileExtractor; +import electrostatic4j.snaploader.filesystem.FileLocator; +import electrostatic4j.snaploader.platform.util.DefaultDynamicLibraries; +import electrostatic4j.snaploader.platform.NativeDynamicLibrary; +import electrostatic4j.snaploader.platform.util.NativeVariant; +import electrostatic4j.snaploader.platform.util.PlatformPredicate; +import electrostatic4j.snaploader.platform.util.DefaultPropertiesProvider; +import electrostatic4j.snaploader.LoadingCriterion; + +/** + * Tests basic features of the {@link NativeBinaryLoader} API. + * + * @author pavl_g + */ +public final class TestBrokenFeatures { + + protected static final LibraryInfo libraryInfo = new LibraryInfo(getJarFilePath(), + new DirectoryPath(DefaultDynamicLibraries.LINUX_X86.getPlatformDirectory()), + getLibraryBaseName(), + getLibrariesAbsolutePath()); + + protected static NativeBinaryLoader loader; + + public static final NativeDynamicLibrary[] libraries = new NativeDynamicLibrary[] { + DefaultDynamicLibraries.LINUX_X86, + 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, + DefaultDynamicLibraries.MAC_X86_64, + }; + + public static void main(String[] args) throws Exception { + if (loader == null) { + loader = new NativeBinaryLoader(libraryInfo); + } + loader.registerNativeLibraries(libraries).initPlatformLibrary(); + loader.setLoggingEnabled(false); + loader.setRetryWithCleanExtraction(true); + /* Native dynamic library properties */ + printDetails(loader); + loader.setLibraryExtractionListener(new FileExtractionListener() { + @Override + public void onExtractionCompleted(FileExtractor fileExtractor) { + System.out.println("Extracted Successfully!"); + } + + @Override + public void onExtractionFailure(FileExtractor fileExtractor, Throwable throwable) { + System.err.println(throwable.toString()); + } + + @Override + public void onExtractionFinalization(FileExtractor fileExtractor, FileLocator fileLocator) { + System.out.println("Finalization State has been reached!"); + } + }); + loader.loadLibrary(LoadingCriterion.INCREMENTAL_LOADING); + } + + protected static void printDetails(NativeBinaryLoader loader) { + System.out.println("--------------------------------------------------------------"); + System.out.println("OS: " + NativeVariant.OS_NAME.getProperty()); + System.out.println("ARCH: " + NativeVariant.OS_ARCH.getProperty()); + System.out.println("VM: " + NativeVariant.JVM.getProperty()); + System.out.println("--------------------------------------------------------------"); + System.out.println("Jar Path: " + loader.getNativeDynamicLibrary().getJarPath()); + System.out.println("Library Directory: " + loader.getNativeDynamicLibrary().getPlatformDirectory()); + System.out.println("Compressed library path: " + loader.getNativeDynamicLibrary().getCompressedLibrary()); + System.out.println("Extracted library absolute path: " + loader.getNativeDynamicLibrary().getExtractedLibrary()); + System.out.println("Is Extracted: " + loader.getNativeDynamicLibrary().isExtracted()); + System.out.println("--------------------------------------------------------------"); + } + + protected static DirectoryPath getLibrariesAbsolutePath() { + return new DirectoryPath(DefaultPropertiesProvider.USER_DIR.getSystemProperty(), "libs"); + } + + protected static DirectoryPath getJarFilePath() { + return new DirectoryPath(getLibrariesAbsolutePath().getPath(), getJarFile()); + } + + protected static String getNativeDynamicLibraryPath() { + return getLibrariesAbsolutePath().getPath() + + DefaultPropertiesProvider.FILE_SEPARATOR.getSystemProperty() + + "lib" + getLibraryBaseName() + ".so"; + } + + protected static String getJarFile() { + return "jme3-alloc-desktop-1.0.0-pre-gamma-2.jar"; + } + + protected static String getLibraryBaseName() { + return "jmealloc"; + } +} \ No newline at end of file From e87ffc84a8f7f96af2753e12f2fa2e6f368f6982 Mon Sep 17 00:00:00 2001 From: pavl-g Date: Sun, 4 Oct 2026 21:51:52 +0300 Subject: [PATCH 04/15] NativeBinaryLoader: library existence utilities and exception --- .../snaploader/NativeBinaryLoader.java | 9 +++- .../platform/NativeDynamicLibrary.java | 7 +++ .../throwable/LibraryNotFoundException.java | 47 +++++++++++++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 snaploader/src/main/java/electrostatic4j/snaploader/throwable/LibraryNotFoundException.java diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java b/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java index 292ccc3..785ab05 100644 --- a/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java +++ b/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2025, The Electrostatic-Sandbox Distributed Simulation Framework, jSnapLoader + * Copyright (c) 2023-2026, The Electrostatic-Sandbox Distributed Simulation Framework, jSnapLoader * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,6 +33,7 @@ package electrostatic4j.snaploader; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.nio.file.FileSystems; import java.util.Arrays; @@ -49,6 +50,7 @@ import electrostatic4j.snaploader.platform.util.NativeVariant; import electrostatic4j.snaploader.platform.util.PropertiesControllerNamespace; import electrostatic4j.snaploader.platform.util.PropertiesController; +import electrostatic4j.snaploader.throwable.LibraryNotFoundException; import electrostatic4j.snaploader.throwable.LoadingRetryExhaustionException; import electrostatic4j.snaploader.throwable.UnSupportedSystemError; import electrostatic4j.snaploader.util.CallingStackMetaData; @@ -337,6 +339,9 @@ protected void loadSystemBinary(NativeDynamicLibrary dynamicLibrary) { */ protected void loadBinary(NativeDynamicLibrary library, LoadingCriterion loadingCriterion) throws Exception { try { + if (!nativeDynamicLibrary.exists()) { + throw new LibraryNotFoundException("Library " + nativeDynamicLibrary.getExtractedLibrary() + " not found!"); + } System.load(library.getExtractedLibrary()); SnapLoaderLogger.log(Level.INFO, getClass().getName(), "loadBinary", "Successfully loaded library: " + library.getExtractedLibrary()); @@ -344,7 +349,7 @@ protected void loadBinary(NativeDynamicLibrary library, LoadingCriterion loading nativeBinaryLoadingListener.onLoadingSuccess(this, new CallingStackMetaData(Thread.currentThread().getStackTrace()[1], loadingCriterion)); } - } catch (final UnsatisfiedLinkError error) { + } catch (final UnsatisfiedLinkError | FileNotFoundException error) { SnapLoaderLogger.log(Level.SEVERE, getClass().getName(), "loadBinary", "Cannot load the dynamic library: " + library.getExtractedLibrary(), error); if (nativeBinaryLoadingListener != null) { diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/platform/NativeDynamicLibrary.java b/snaploader/src/main/java/electrostatic4j/snaploader/platform/NativeDynamicLibrary.java index b252cc7..c9a1148 100644 --- a/snaploader/src/main/java/electrostatic4j/snaploader/platform/NativeDynamicLibrary.java +++ b/snaploader/src/main/java/electrostatic4j/snaploader/platform/NativeDynamicLibrary.java @@ -146,6 +146,13 @@ public void initWithLibraryInfo(LibraryInfo libraryInfo) { } } + public boolean exists() { + if (jarPath == null || libraryFile == null || directoryPath == null) { + return false; + } + return new File(getExtractedLibrary()).exists(); + } + /** * Retrieves the absolute path for the jar compression as specified by the {@link LibraryInfo} API. * diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/throwable/LibraryNotFoundException.java b/snaploader/src/main/java/electrostatic4j/snaploader/throwable/LibraryNotFoundException.java new file mode 100644 index 0000000..a9df55d --- /dev/null +++ b/snaploader/src/main/java/electrostatic4j/snaploader/throwable/LibraryNotFoundException.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023-2026, The Electrostatic-Sandbox Distributed Simulation Framework, jSnapLoader + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'Electrostatic-Sandbox' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package electrostatic4j.snaploader.throwable; + +import java.io.FileNotFoundException; + +/** + * A business exception that is thrown to indicate that a library, that is + * tried to be loaded, doesn't exist. + * + * @author pavl_g + */ +public class LibraryNotFoundException extends FileNotFoundException { + public LibraryNotFoundException(String message) { + super(message); + } +} From d2a5d622f84544361838b6008292e12f7ecdccb8 Mon Sep 17 00:00:00 2001 From: pavl-g Date: Sun, 4 Oct 2026 21:52:27 +0300 Subject: [PATCH 05/15] TestBrokenFeatures: enabled logging --- .../snaploader/examples/TestBrokenFeatures.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBrokenFeatures.java b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBrokenFeatures.java index f9b1d9a..9c29434 100644 --- a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBrokenFeatures.java +++ b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBrokenFeatures.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2024, The Electrostatic-Sandbox Distributed Simulation Framework, jSnapLoader + * Copyright (c) 2023-2026, The Electrostatic-Sandbox Distributed Simulation Framework, jSnapLoader * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -73,7 +73,7 @@ public static void main(String[] args) throws Exception { loader = new NativeBinaryLoader(libraryInfo); } loader.registerNativeLibraries(libraries).initPlatformLibrary(); - loader.setLoggingEnabled(false); + loader.setLoggingEnabled(true); loader.setRetryWithCleanExtraction(true); /* Native dynamic library properties */ printDetails(loader); From dde94d946486918bca16d0cffacdb7a3cafc4c6b Mon Sep 17 00:00:00 2001 From: pavl-g Date: Sun, 4 Oct 2026 21:54:24 +0300 Subject: [PATCH 06/15] workflows/build-test: added TestBrokenFeatures task --- .github/workflows/build-test.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 8a484e4..89e79a9 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -104,5 +104,9 @@ jobs: - name: Run TestCpuFeatures run: ./gradlew :snaploader-examples:TestCpuFeatures :snaploader-examples:run + - name: Run TestBrokenFeatures + run: ./gradlew :snaploader-examples:ReflectiveLauncher :snaploader-examples:run --args="electrostatic4j.snaploader.examples.TestBrokenFeatures" + - name: List extracted files run: ls ./snaploader-examples/libs/ + From 7856370c49d18d8bafa428d042b3dea1ac8bd27c Mon Sep 17 00:00:00 2001 From: pavl-g Date: Sun, 4 Oct 2026 22:21:36 +0300 Subject: [PATCH 07/15] TestBrokenFeatures: added a standard way to deal with exceptions and errors --- .../examples/TestBrokenFeatures.java | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBrokenFeatures.java b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBrokenFeatures.java index 9c29434..f738052 100644 --- a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBrokenFeatures.java +++ b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBrokenFeatures.java @@ -34,6 +34,7 @@ import electrostatic4j.snaploader.LibraryInfo; import electrostatic4j.snaploader.NativeBinaryLoader; +import electrostatic4j.snaploader.NativeBinaryLoadingListener; import electrostatic4j.snaploader.filesystem.DirectoryPath; import electrostatic4j.snaploader.filesystem.FileExtractionListener; import electrostatic4j.snaploader.filesystem.FileExtractor; @@ -44,6 +45,7 @@ import electrostatic4j.snaploader.platform.util.PlatformPredicate; import electrostatic4j.snaploader.platform.util.DefaultPropertiesProvider; import electrostatic4j.snaploader.LoadingCriterion; +import electrostatic4j.snaploader.util.CallingStackMetaData; /** * Tests basic features of the {@link NativeBinaryLoader} API. @@ -73,10 +75,27 @@ public static void main(String[] args) throws Exception { loader = new NativeBinaryLoader(libraryInfo); } loader.registerNativeLibraries(libraries).initPlatformLibrary(); - loader.setLoggingEnabled(true); + loader.setLoggingEnabled(false); loader.setRetryWithCleanExtraction(true); /* Native dynamic library properties */ printDetails(loader); + loader.setNativeBinaryLoadingListener(new NativeBinaryLoadingListener() { + @Override + public void onLoadingSuccess(NativeBinaryLoader nativeBinaryLoader, CallingStackMetaData callingStackMetaData) { + + } + + @Override + public void onLoadingFailure(NativeBinaryLoader nativeBinaryLoader, CallingStackMetaData callingStackMetaData) { + System.err.println(callingStackMetaData.getErrorCause()); + } + + @Override + public void onRetryCriterionExecution(NativeBinaryLoader nativeBinaryLoader, CallingStackMetaData callingStackMetaData) { + + } + }); + loader.setLibraryExtractionListener(new FileExtractionListener() { @Override public void onExtractionCompleted(FileExtractor fileExtractor) { @@ -93,6 +112,7 @@ public void onExtractionFinalization(FileExtractor fileExtractor, FileLocator fi System.out.println("Finalization State has been reached!"); } }); + loader.loadLibrary(LoadingCriterion.INCREMENTAL_LOADING); } From 978b3cb0e3ce73715ad80e9be5dd49074fcdbe14 Mon Sep 17 00:00:00 2001 From: pavl-g Date: Wed, 7 Oct 2026 06:47:38 +0300 Subject: [PATCH 08/15] NativeBinaryLoader: refactored anti-failure mechanisms to be through exception handlers --- .../ConcurrentNativeBinaryLoader.java | 8 +- .../snaploader/NativeBinaryLoader.java | 95 +++++-------------- .../filesystem/FileExtractionListener.java | 9 -- .../filesystem/FileLocalizingListener.java | 10 -- 4 files changed, 30 insertions(+), 92 deletions(-) diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/ConcurrentNativeBinaryLoader.java b/snaploader/src/main/java/electrostatic4j/snaploader/ConcurrentNativeBinaryLoader.java index 1226689..665268e 100644 --- a/snaploader/src/main/java/electrostatic4j/snaploader/ConcurrentNativeBinaryLoader.java +++ b/snaploader/src/main/java/electrostatic4j/snaploader/ConcurrentNativeBinaryLoader.java @@ -35,6 +35,10 @@ import java.util.List; import java.util.concurrent.locks.ReentrantLock; import electrostatic4j.snaploader.platform.NativeDynamicLibrary; +import electrostatic4j.snaploader.throwable.FileExtractionProcessingException; +import electrostatic4j.snaploader.throwable.FilesystemResourceInitializationException; +import electrostatic4j.snaploader.throwable.FilesystemResourceScavengingException; +import electrostatic4j.snaploader.throwable.LoadingRetryExhaustionException; import electrostatic4j.snaploader.throwable.UnSupportedSystemError; /** @@ -71,7 +75,7 @@ public NativeBinaryLoader initPlatformLibrary() throws UnSupportedSystemError { } @Override - public NativeBinaryLoader loadLibrary(LoadingCriterion criterion) throws Exception { + public NativeBinaryLoader loadLibrary(LoadingCriterion criterion) throws FilesystemResourceScavengingException, LoadingRetryExhaustionException, FilesystemResourceInitializationException, FileExtractionProcessingException { try { /* CRITICAL SECTION STARTS */ lock.lock(); @@ -83,7 +87,7 @@ public NativeBinaryLoader loadLibrary(LoadingCriterion criterion) throws Excepti } @Override - protected void cleanExtractBinary(NativeDynamicLibrary library) throws Exception { + protected void cleanExtractBinary(NativeDynamicLibrary library) throws FilesystemResourceScavengingException, FileExtractionProcessingException, FilesystemResourceInitializationException { try { /* CRITICAL SECTION STARTS */ lock.lock(); diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java b/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java index 785ab05..0b8b63f 100644 --- a/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java +++ b/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java @@ -33,7 +33,6 @@ package electrostatic4j.snaploader; import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.nio.file.FileSystems; import java.util.Arrays; @@ -45,11 +44,13 @@ import electrostatic4j.snaploader.filesystem.FileLocalizingListener; import electrostatic4j.snaploader.filesystem.FileLocator; import electrostatic4j.snaploader.library.LibraryExtractor; -import electrostatic4j.snaploader.library.LibraryLocator; import electrostatic4j.snaploader.platform.NativeDynamicLibrary; import electrostatic4j.snaploader.platform.util.NativeVariant; import electrostatic4j.snaploader.platform.util.PropertiesControllerNamespace; import electrostatic4j.snaploader.platform.util.PropertiesController; +import electrostatic4j.snaploader.throwable.FileExtractionProcessingException; +import electrostatic4j.snaploader.throwable.FilesystemResourceInitializationException; +import electrostatic4j.snaploader.throwable.FilesystemResourceScavengingException; import electrostatic4j.snaploader.throwable.LibraryNotFoundException; import electrostatic4j.snaploader.throwable.LoadingRetryExhaustionException; import electrostatic4j.snaploader.throwable.UnSupportedSystemError; @@ -180,7 +181,7 @@ public NativeBinaryLoader initPlatformLibrary() throws UnSupportedSystemError { * @return this instance for chained invocations * @throws IOException if the library to extract is not present in the jar filesystem */ - public NativeBinaryLoader loadLibrary(LoadingCriterion criterion) throws Exception { + public NativeBinaryLoader loadLibrary(LoadingCriterion criterion) throws FilesystemResourceScavengingException, LoadingRetryExhaustionException, FilesystemResourceInitializationException, FileExtractionProcessingException { if (nativeDynamicLibrary == null || libraryInfo == null) { throw new IllegalArgumentException("Native library data structures cannot be null!"); } @@ -333,11 +334,11 @@ protected void loadSystemBinary(NativeDynamicLibrary dynamicLibrary) { * * @param library the platform-specific library to load * @param loadingCriterion pass the loading criterion condition to the calling stack metadata structure - * @throws IOException in case the binary to be extracted is not found on the specified jar + * @throws FilesystemResourceInitializationException in case the binary to be extracted is not found on the specified jar * @throws LoadingRetryExhaustionException if the number of loading failure exceeds the specified * number. */ - protected void loadBinary(NativeDynamicLibrary library, LoadingCriterion loadingCriterion) throws Exception { + protected void loadBinary(NativeDynamicLibrary library, LoadingCriterion loadingCriterion) throws FilesystemResourceInitializationException, FilesystemResourceScavengingException, LoadingRetryExhaustionException, FileExtractionProcessingException { try { if (!nativeDynamicLibrary.exists()) { throw new LibraryNotFoundException("Library " + nativeDynamicLibrary.getExtractedLibrary() + " not found!"); @@ -349,7 +350,7 @@ protected void loadBinary(NativeDynamicLibrary library, LoadingCriterion loading nativeBinaryLoadingListener.onLoadingSuccess(this, new CallingStackMetaData(Thread.currentThread().getStackTrace()[1], loadingCriterion)); } - } catch (final UnsatisfiedLinkError | FileNotFoundException error) { + } catch (Throwable error) { SnapLoaderLogger.log(Level.SEVERE, getClass().getName(), "loadBinary", "Cannot load the dynamic library: " + library.getExtractedLibrary(), error); if (nativeBinaryLoadingListener != null) { @@ -378,10 +379,10 @@ protected void loadBinary(NativeDynamicLibrary library, LoadingCriterion loading * Cleanly extracts and loads the native binary to the current [user.dir]. * * @param library the platform-specific library to extract and load - * @throws IOException in case the binary to be extracted is not found on the specified jar, or an + * @throws FilesystemResourceInitializationException in case the binary to be extracted is not found on the specified jar, or an * interrupted I/O operation has occurred */ - protected void cleanExtractBinary(NativeDynamicLibrary library) throws Exception { + protected void cleanExtractBinary(NativeDynamicLibrary library) throws FilesystemResourceInitializationException, FilesystemResourceScavengingException, FileExtractionProcessingException { libraryExtractor = initializeLibraryExtractor(library); SnapLoaderLogger.log(Level.INFO, getClass().getName(), "cleanExtractBinary", "File extractor handler initialized!"); @@ -409,17 +410,6 @@ public void onExtractionCompleted(FileExtractor fileExtractor) { } } - @Override - public void onExtractionFailure(FileExtractor fileExtractor, Throwable throwable) { - SnapLoaderLogger.log(Level.SEVERE, getClass().getName(), - "cleanExtractBinary", "Extraction has failed!", throwable); - - // bind the extraction lifecycle to the user application - if (libraryExtractionListener != null) { - libraryExtractionListener.onExtractionFailure(fileExtractor, throwable); - } - } - @Override public void onExtractionFinalization(FileExtractor fileExtractor, FileLocator fileLocator) { try { @@ -438,6 +428,7 @@ public void onExtractionFinalization(FileExtractor fileExtractor, FileLocator fi } } }); + libraryExtractor.extract(); } @@ -447,61 +438,23 @@ public void onExtractionFinalization(FileExtractor fileExtractor, FileLocator fi * * @param library the native dynamic library to load * @return a new FileExtractor object that represents an output stream provider - * @throws IOException if the jar filesystem to be located is not found, or if the extraction destination is not found + * @throws FilesystemResourceInitializationException if the jar filesystem to be located is not found, or if the extraction destination is not found */ - protected FileExtractor initializeLibraryExtractor(NativeDynamicLibrary library) throws Exception { - FileExtractor extractor; - if (library.getJarPath() != null) { - // use an extractor with the external jar routine - extractor = new LibraryExtractor(new JarFile(library.getJarPath()), library.getCompressedLibrary(), library.getExtractedLibrary()); - } else { - // use an extractor with the classpath routine - extractor = new LibraryExtractor(library.getCompressedLibrary(), library.getExtractedLibrary()); - } - extractor.initialize(0); - final LibraryLocator fileLocator = preInitLibraryLocator(extractor); - fileLocator.initialize(0); - return extractor; - } - - protected LibraryLocator preInitLibraryLocator(FileExtractor extractor) { - extractor.getFileLocator().setFileLocalizingListener(new FileLocalizingListener() { - @Override - public void onFileLocalizationSuccess(FileLocator locator) { - SnapLoaderLogger.log(Level.INFO, getClass().getName(), "preInitLibraryLocator", - "Locating native libraries has succeeded!"); - - // bind the library locator lifecycle to the user application - if (libraryLocalizingListener != null) { - libraryLocalizingListener.onFileLocalizationSuccess(locator); - } - } - - @Override - public void onFileLocalizationFailure(FileLocator locator, Throwable throwable) { - SnapLoaderLogger.log(Level.SEVERE, getClass().getName(), "preInitLibraryLocator", - "Locating native libraries has failed!", throwable); + protected FileExtractor initializeLibraryExtractor(NativeDynamicLibrary library) throws FilesystemResourceInitializationException, FilesystemResourceScavengingException { + FileExtractor extractor; + if (library.getJarPath() != null) { try { - extractor.close(); - } catch (Exception e) { - SnapLoaderLogger.log(Level.SEVERE, getClass().getName(), - "initializeLibraryExtractor", "File locator closure failed!", e); - } - - // bind the library locator lifecycle to the user application - if (libraryLocalizingListener != null) { - libraryLocalizingListener.onFileLocalizationFailure(locator, throwable); - } - - // make use of the loader listeners - if (nativeBinaryLoadingListener != null) { - // a file locator and extractor loader is always a CLEAN_EXTRACTION regarding - // the loading criterion - nativeBinaryLoadingListener.onLoadingFailure(NativeBinaryLoader.this, - new CallingStackMetaData(Thread.currentThread().getStackTrace()[1], LoadingCriterion.CLEAN_EXTRACTION, throwable)); + // use an extractor with the external jar routine + extractor = new LibraryExtractor(new JarFile(library.getJarPath()), library.getCompressedLibrary(), library.getExtractedLibrary()); + } catch (IOException e) { + throw new FilesystemResourceInitializationException("Error while initializing the file extractor!", e); } + } else { + // use an extractor with the classpath routine + extractor = new LibraryExtractor(library.getCompressedLibrary(), library.getExtractedLibrary()); } - }); - return (LibraryLocator) extractor.getFileLocator(); + extractor.initialize(0); + + return extractor; } } diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileExtractionListener.java b/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileExtractionListener.java index 5d30450..72090d9 100644 --- a/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileExtractionListener.java +++ b/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileExtractionListener.java @@ -55,15 +55,6 @@ public interface FileExtractionListener { */ void onExtractionCompleted(FileExtractor fileExtractor); - /** - * Dispatched when the extraction process has failed with a throwable - * component. - * - * @param fileExtractor the extractor in-command. - * @param throwable the throwable captured from the FileExtractor API. - */ - void onExtractionFailure(FileExtractor fileExtractor, Throwable throwable); - /** * Dispatched when the extraction process is finalized, at this point, manually * freeing active resources should be attained. diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileLocalizingListener.java b/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileLocalizingListener.java index ce8244e..4d546ae 100644 --- a/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileLocalizingListener.java +++ b/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileLocalizingListener.java @@ -48,14 +48,4 @@ public interface FileLocalizingListener { * @param locator the associated file locator object. */ void onFileLocalizationSuccess(FileLocator locator); - - /** - * Dispatched whenever the file input stream is invalid, hence the specified - * file cannot be localized for the extraction process. - * - * @param locator the associated file locator object. - * @param throwable the throwable object, typically indicating a failure - * to locate the file inside the compression. - */ - void onFileLocalizationFailure(FileLocator locator, Throwable throwable); } From 62a19162e5ecf2057d7def24957638fc48858673 Mon Sep 17 00:00:00 2001 From: pavl-g Date: Wed, 7 Oct 2026 06:49:09 +0300 Subject: [PATCH 09/15] FileExtractor: extraction depends on locator --- .../filesystem/ConcurrentFileExtractor.java | 5 +++- .../snaploader/filesystem/FileExtractor.java | 28 ++++++++++++++----- .../snaploader/filesystem/FileLocator.java | 20 +++++++------ 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/ConcurrentFileExtractor.java b/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/ConcurrentFileExtractor.java index 522e979..fb917f3 100644 --- a/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/ConcurrentFileExtractor.java +++ b/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/ConcurrentFileExtractor.java @@ -35,6 +35,9 @@ import java.io.IOException; import java.util.concurrent.locks.ReentrantLock; +import electrostatic4j.snaploader.throwable.FileExtractionProcessingException; +import electrostatic4j.snaploader.throwable.FilesystemResourceScavengingException; + /** * A thread-safe implementation of the filesystem extractor API. * @@ -65,7 +68,7 @@ protected ConcurrentFileExtractor() { } @Override - public void extract() throws IOException { + public void extract() throws FileExtractionProcessingException, FilesystemResourceScavengingException { try { /* CRITICAL SECTION STARTS */ lock.lock(); diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileExtractor.java b/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileExtractor.java index 6d7788f..48db0a1 100644 --- a/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileExtractor.java +++ b/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileExtractor.java @@ -32,10 +32,11 @@ package electrostatic4j.snaploader.filesystem; +import electrostatic4j.snaploader.throwable.FileExtractionProcessingException; import electrostatic4j.snaploader.throwable.FilesystemResourceInitializationException; +import electrostatic4j.snaploader.throwable.FilesystemResourceScavengingException; import electrostatic4j.snaploader.util.SnapLoaderLogger; import electrostatic4j.snaploader.util.StreamObjectValidator; - import java.io.*; import java.util.logging.Level; @@ -88,7 +89,11 @@ protected FileExtractor() { } @Override - public void initialize(int size) throws Exception { + public void initialize(int size) throws FilesystemResourceInitializationException, + FilesystemResourceScavengingException { + if (fileLocator == null) { + throw new IllegalArgumentException("File locator cannot be null!"); + } // 1) sanity-check for double initializing // 2) sanity-check for pre-initialization using other routines if (this.fileOutputStream != null) { @@ -97,6 +102,7 @@ public void initialize(int size) throws Exception { return; } try { + fileLocator.initialize(size); if (size > 0) { this.fileOutputStream = new BufferedOutputStream( new FileOutputStream(destination), size); @@ -109,7 +115,12 @@ public void initialize(int size) throws Exception { SnapLoaderLogger.log(Level.INFO, getClass().getName(), "initialize(int)", "File extractor initialized with hash key #" + getHashKey()); } catch (Exception e) { - close(); + try { + close(); + } catch (Exception cause) { + throw new FilesystemResourceScavengingException( + "Failed to close the file extractor handler #" + getHashKey(), e); + } throw new FilesystemResourceInitializationException( "Failed to initialize the file extractor handler #" + getHashKey(), e); } @@ -127,7 +138,7 @@ public void initialize(int size) throws Exception { * @throws FileNotFoundException if the file locator has failed to locate the file inside the compression * for the extraction process. */ - public void extract() throws IOException, FileNotFoundException { + public void extract() throws FileExtractionProcessingException, FilesystemResourceScavengingException { try { /* uses buffered streams */ /* buffered byte streams provide a constant memory allocation @@ -160,9 +171,12 @@ public void extract() throws IOException, FileNotFoundException { // as a result of trying to load corrupted files // on the next runtime... delete(); - if (fileExtractionListener != null) { - fileExtractionListener.onExtractionFailure(this, e); + try { + close(); + } catch (Exception ex) { + throw new FilesystemResourceScavengingException(); } + throw new FileExtractionProcessingException("", e); // release the native resources anyway! } finally { if (fileExtractionListener != null) { @@ -178,7 +192,7 @@ public void extract() throws IOException, FileNotFoundException { * @return true if the file has been deleted, false otherwise if the * file is not defined or doesn't exist. */ - protected boolean delete() { + public boolean delete() { if (extractableFile == null || !extractableFile.exists()) { return false; } diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileLocator.java b/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileLocator.java index 40aef50..83cd9f9 100644 --- a/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileLocator.java +++ b/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileLocator.java @@ -33,6 +33,7 @@ package electrostatic4j.snaploader.filesystem; import electrostatic4j.snaploader.throwable.FilesystemResourceInitializationException; +import electrostatic4j.snaploader.throwable.FilesystemResourceScavengingException; import electrostatic4j.snaploader.util.SnapLoaderLogger; import electrostatic4j.snaploader.util.StreamObjectValidator; @@ -111,10 +112,10 @@ protected FileLocator() { * * @param size the size of the buffered IO in bytes or zero * for auto filesystem size - * @throws IOException if an I/O error has occurred. */ @Override - public void initialize(int size) throws IOException { + public void initialize(int size) throws FilesystemResourceInitializationException, + FilesystemResourceScavengingException { // 1) sanity-check for double initializing if (this.fileInputStream != null) { SnapLoaderLogger.log(Level.INFO, getClass().getName(), "initialize(int)", @@ -138,21 +139,22 @@ public void initialize(int size) throws IOException { fileLocalizingListener.onFileLocalizationSuccess(this); } } catch (Exception e) { - close(); + try { + close(); + } catch (IOException ex) { + throw new FilesystemResourceScavengingException("File locator resources closure failed!", ex); + } // fire the failure listener when file localization fails and pass // the causative exception - if (fileLocalizingListener != null) { - fileLocalizingListener.onFileLocalizationFailure(this, e); - } + throw new FilesystemResourceInitializationException("File locator initialization failed!", e); } } /** * Commands for the classpath routines. * - * @throws FilesystemResourceInitializationException if the classpath routine fails to locate the file. */ - protected void classPathRoutine() throws FilesystemResourceInitializationException { + protected void classPathRoutine() { SnapLoaderLogger.log(Level.INFO, getClass().getName(), "initialize(int)", "File locator initialized using classpath routine with hash key #" + getHashKey()); // Use the AppClassLoader, a BuiltinClassLoader to get the resources from the classpath @@ -174,7 +176,7 @@ protected void classPathRoutine() throws FilesystemResourceInitializationExcepti * (warning: file expansion and truncation rules are applied). * @throws IOException if an I/O error has occurred. */ - protected void externalCompressionRoutine(int size) throws IOException { + protected void externalCompressionRoutine(int size) throws IOException, FilesystemResourceInitializationException { final ZipEntry zipEntry = compression.getEntry(filePath); StreamObjectValidator.validateAndThrow(zipEntry, StreamObjectValidator.COMPRESSION_FILE_LOCALIZING_FAIL); if (size > 0) { From 3dc70added358e479422a32f96bc1164241e9495 Mon Sep 17 00:00:00 2001 From: pavl-g Date: Wed, 7 Oct 2026 06:50:19 +0300 Subject: [PATCH 10/15] Throwables: introduced organized exceptions --- .../FileExtractionProcessingException.java | 23 +++++++++++++++++++ .../throwable/LibraryInitException.java | 7 ++++++ 2 files changed, 30 insertions(+) create mode 100644 snaploader/src/main/java/electrostatic4j/snaploader/throwable/FileExtractionProcessingException.java create mode 100644 snaploader/src/main/java/electrostatic4j/snaploader/throwable/LibraryInitException.java diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/throwable/FileExtractionProcessingException.java b/snaploader/src/main/java/electrostatic4j/snaploader/throwable/FileExtractionProcessingException.java new file mode 100644 index 0000000..9ae5302 --- /dev/null +++ b/snaploader/src/main/java/electrostatic4j/snaploader/throwable/FileExtractionProcessingException.java @@ -0,0 +1,23 @@ +package electrostatic4j.snaploader.throwable; + +public class FileExtractionProcessingException extends RuntimeException { + public FileExtractionProcessingException(String message) { + super(message); + } + + public FileExtractionProcessingException() { + } + + public FileExtractionProcessingException(String message, Throwable cause) { + super(message, cause); + } + + public FileExtractionProcessingException(Throwable cause) { + super(cause); + } + + public FileExtractionProcessingException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + +} diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/throwable/LibraryInitException.java b/snaploader/src/main/java/electrostatic4j/snaploader/throwable/LibraryInitException.java new file mode 100644 index 0000000..035a5ef --- /dev/null +++ b/snaploader/src/main/java/electrostatic4j/snaploader/throwable/LibraryInitException.java @@ -0,0 +1,7 @@ +package electrostatic4j.snaploader.throwable; + +public class LibraryInitException extends RuntimeException { + public LibraryInitException(String message) { + super(message); + } +} From defdca71a771a8e5d7622cf04ad4d92519a234cc Mon Sep 17 00:00:00 2001 From: pavl-g Date: Wed, 7 Oct 2026 06:51:25 +0300 Subject: [PATCH 11/15] NativeDynamicLibrary: LibraryInitException implementation --- .../snaploader/platform/NativeDynamicLibrary.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/platform/NativeDynamicLibrary.java b/snaploader/src/main/java/electrostatic4j/snaploader/platform/NativeDynamicLibrary.java index c9a1148..7c658c5 100644 --- a/snaploader/src/main/java/electrostatic4j/snaploader/platform/NativeDynamicLibrary.java +++ b/snaploader/src/main/java/electrostatic4j/snaploader/platform/NativeDynamicLibrary.java @@ -39,6 +39,7 @@ import electrostatic4j.snaploader.platform.util.NativeVariant; import electrostatic4j.snaploader.platform.util.PlatformPredicate; import electrostatic4j.snaploader.platform.util.DefaultPropertiesProvider; +import electrostatic4j.snaploader.throwable.LibraryInitException; /** * Represents a filesystem to a platform-specific binary inside @@ -146,9 +147,9 @@ public void initWithLibraryInfo(LibraryInfo libraryInfo) { } } - public boolean exists() { - if (jarPath == null || libraryFile == null || directoryPath == null) { - return false; + public boolean exists() throws LibraryInitException { + if (libraryFile == null) { + throw new LibraryInitException("Library file name cannot be null!"); } return new File(getExtractedLibrary()).exists(); } From 4086c1f0131b6bb2d4f17fd167070f7f8316d5ff Mon Sep 17 00:00:00 2001 From: pavl-g Date: Wed, 7 Oct 2026 06:52:04 +0300 Subject: [PATCH 12/15] StreamObjectValidator: throws keywords at methods signatures --- .../snaploader/util/StreamObjectValidator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/util/StreamObjectValidator.java b/snaploader/src/main/java/electrostatic4j/snaploader/util/StreamObjectValidator.java index cae68d7..c116e5f 100644 --- a/snaploader/src/main/java/electrostatic4j/snaploader/util/StreamObjectValidator.java +++ b/snaploader/src/main/java/electrostatic4j/snaploader/util/StreamObjectValidator.java @@ -48,14 +48,14 @@ public final class StreamObjectValidator { private StreamObjectValidator() { } - public static void validateAndThrow(final StreamProvider object, final String message, final Throwable cause) { + public static void validateAndThrow(final StreamProvider object, final String message, final Throwable cause) throws FilesystemResourceInitializationException { if (object != null) { return; } throw new FilesystemResourceInitializationException(message, cause); } - public static void validateAndThrow(final Object object, final String message) { + public static void validateAndThrow(final Object object, final String message) throws FilesystemResourceInitializationException { if (object != null) { return; } From 86afc5b8b42cdf43467eb0367cf103c53965b623 Mon Sep 17 00:00:00 2001 From: pavl-g Date: Wed, 7 Oct 2026 06:52:33 +0300 Subject: [PATCH 13/15] snaploader-examples: applied API changes --- .../snaploader/examples/TestBrokenFeatures.java | 14 +++++++------- .../examples/TestFilesystemMemoryLeak.java | 5 ----- .../snaploader/examples/TestZipExtractor.java | 5 ----- .../snaploader/examples/api/NativeDllLoader.java | 4 ---- 4 files changed, 7 insertions(+), 21 deletions(-) diff --git a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBrokenFeatures.java b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBrokenFeatures.java index f738052..ae4d6f6 100644 --- a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBrokenFeatures.java +++ b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBrokenFeatures.java @@ -38,6 +38,7 @@ import electrostatic4j.snaploader.filesystem.DirectoryPath; import electrostatic4j.snaploader.filesystem.FileExtractionListener; import electrostatic4j.snaploader.filesystem.FileExtractor; +import electrostatic4j.snaploader.filesystem.FileLocalizingListener; import electrostatic4j.snaploader.filesystem.FileLocator; import electrostatic4j.snaploader.platform.util.DefaultDynamicLibraries; import electrostatic4j.snaploader.platform.NativeDynamicLibrary; @@ -45,6 +46,10 @@ import electrostatic4j.snaploader.platform.util.PlatformPredicate; import electrostatic4j.snaploader.platform.util.DefaultPropertiesProvider; import electrostatic4j.snaploader.LoadingCriterion; +import electrostatic4j.snaploader.throwable.FileExtractionProcessingException; +import electrostatic4j.snaploader.throwable.FilesystemResourceInitializationException; +import electrostatic4j.snaploader.throwable.FilesystemResourceScavengingException; +import electrostatic4j.snaploader.throwable.LoadingRetryExhaustionException; import electrostatic4j.snaploader.util.CallingStackMetaData; /** @@ -70,12 +75,12 @@ public final class TestBrokenFeatures { DefaultDynamicLibraries.MAC_X86_64, }; - public static void main(String[] args) throws Exception { + public static void main(String[] args) throws FilesystemResourceScavengingException, LoadingRetryExhaustionException, FilesystemResourceInitializationException, FileExtractionProcessingException { if (loader == null) { loader = new NativeBinaryLoader(libraryInfo); } loader.registerNativeLibraries(libraries).initPlatformLibrary(); - loader.setLoggingEnabled(false); + loader.setLoggingEnabled(true); loader.setRetryWithCleanExtraction(true); /* Native dynamic library properties */ printDetails(loader); @@ -102,11 +107,6 @@ public void onExtractionCompleted(FileExtractor fileExtractor) { System.out.println("Extracted Successfully!"); } - @Override - public void onExtractionFailure(FileExtractor fileExtractor, Throwable throwable) { - System.err.println(throwable.toString()); - } - @Override public void onExtractionFinalization(FileExtractor fileExtractor, FileLocator fileLocator) { System.out.println("Finalization State has been reached!"); diff --git a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestFilesystemMemoryLeak.java b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestFilesystemMemoryLeak.java index 3eb4b4d..aff10ce 100644 --- a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestFilesystemMemoryLeak.java +++ b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestFilesystemMemoryLeak.java @@ -62,11 +62,6 @@ public void onExtractionCompleted(FileExtractor fileExtractor) { } - @Override - public void onExtractionFailure(FileExtractor fileExtractor, Throwable throwable) { - - } - @Override public void onExtractionFinalization(FileExtractor fileExtractor, FileLocator fileLocator) { Logger.getLogger(TestZipExtractor.class.getName()) diff --git a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestZipExtractor.java b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestZipExtractor.java index 2089a1e..28149d7 100644 --- a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestZipExtractor.java +++ b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestZipExtractor.java @@ -61,11 +61,6 @@ public void onExtractionCompleted(FileExtractor fileExtractor) { } - @Override - public void onExtractionFailure(FileExtractor fileExtractor, Throwable throwable) { - - } - @Override public void onExtractionFinalization(FileExtractor fileExtractor, FileLocator fileLocator) { try { diff --git a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/api/NativeDllLoader.java b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/api/NativeDllLoader.java index f5bb372..2629e59 100644 --- a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/api/NativeDllLoader.java +++ b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/api/NativeDllLoader.java @@ -309,10 +309,6 @@ public void onRetryCriterionExecution(NativeBinaryLoader nativeBinaryLoader, Cal public void onFileLocalizationSuccess(FileLocator locator) { } - @Override - public void onFileLocalizationFailure(FileLocator locator, Throwable throwable) { - } - /** * Sets base feature libraries group strong reference. This command * will only take effect before dispatching the loading From faabfa63025a7ecdd9e97050d0a49810c7a17f79 Mon Sep 17 00:00:00 2001 From: pavl-g Date: Wed, 7 Oct 2026 07:02:43 +0300 Subject: [PATCH 14/15] Documentation errors fix --- .../java/electrostatic4j/snaploader/NativeBinaryLoader.java | 1 - .../electrostatic4j/snaploader/filesystem/FileExtractor.java | 3 --- 2 files changed, 4 deletions(-) diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java b/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java index 0b8b63f..8e053db 100644 --- a/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java +++ b/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java @@ -179,7 +179,6 @@ public NativeBinaryLoader initPlatformLibrary() throws UnSupportedSystemError { * @param criterion the initial loading criterion, either {@link LoadingCriterion#INCREMENTAL_LOADING}, {@link LoadingCriterion#CLEAN_EXTRACTION} * or {@link LoadingCriterion#SYSTEM_LOAD} for loading native dlls from system directories. * @return this instance for chained invocations - * @throws IOException if the library to extract is not present in the jar filesystem */ public NativeBinaryLoader loadLibrary(LoadingCriterion criterion) throws FilesystemResourceScavengingException, LoadingRetryExhaustionException, FilesystemResourceInitializationException, FileExtractionProcessingException { if (nativeDynamicLibrary == null || libraryInfo == null) { diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileExtractor.java b/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileExtractor.java index 48db0a1..ecd3eda 100644 --- a/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileExtractor.java +++ b/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/FileExtractor.java @@ -134,9 +134,6 @@ public void initialize(int size) throws FilesystemResourceInitializationExceptio * attained either through the extraction completed and failure listeners, or through a try-with * resources. * - * @throws IOException if the input/output streams has failed or an interrupted I/O operation has occurred. - * @throws FileNotFoundException if the file locator has failed to locate the file inside the compression - * for the extraction process. */ public void extract() throws FileExtractionProcessingException, FilesystemResourceScavengingException { try { From bd634e6376704bbe195f8dca422a3c8d35984e9b Mon Sep 17 00:00:00 2001 From: pavl-g Date: Wed, 7 Oct 2026 07:03:26 +0300 Subject: [PATCH 15/15] TestBrokenFeatures: caught uncaught exceptions to disable runtime block --- .../snaploader/examples/TestBrokenFeatures.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBrokenFeatures.java b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBrokenFeatures.java index ae4d6f6..a382c6c 100644 --- a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBrokenFeatures.java +++ b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBrokenFeatures.java @@ -32,6 +32,8 @@ package electrostatic4j.snaploader.examples; +import java.io.PrintWriter; + import electrostatic4j.snaploader.LibraryInfo; import electrostatic4j.snaploader.NativeBinaryLoader; import electrostatic4j.snaploader.NativeBinaryLoadingListener; @@ -113,7 +115,11 @@ public void onExtractionFinalization(FileExtractor fileExtractor, FileLocator fi } }); - loader.loadLibrary(LoadingCriterion.INCREMENTAL_LOADING); + try { + loader.loadLibrary(LoadingCriterion.INCREMENTAL_LOADING); + } catch (Exception e) { + e.printStackTrace(System.err); + } } protected static void printDetails(NativeBinaryLoader loader) {