Skip to content

Commit ac75c9c

Browse files
authored
Merge pull request #38 from Electrostat-Lab/stofe-limit-routines
Attempt to fix StackOverflowExceptions from Over Stacked Loading Retries
2 parents bba58e6 + 7dacc8e commit ac75c9c

File tree

7 files changed

+182
-6
lines changed

7 files changed

+182
-6
lines changed
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
44
networkTimeout=10000
55
zipStoreBase=GRADLE_USER_HOME
66
zipStorePath=wrapper/dists

snaploader-examples/build.gradle

+4
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ tasks.register("TestMultiThreading") {
5252
application.mainClass = 'electrostatic4j.snaploader.examples.TestMultiThreading'
5353
}
5454

55+
tasks.register("TestRetryExhaustionException") {
56+
application.mainClass = 'electrostatic4j.snaploader.examples.TestRetryExhaustionException'
57+
}
58+
5559
task copyLibs(type: Copy) {
5660
from (libsDir) {
5761
include '**/*.jar'
27 KB
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* Copyright (c) 2023-2025, The Electrostatic-Sandbox Distributed Simulation Framework, jSnapLoader
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are
7+
* met:
8+
*
9+
* * Redistributions of source code must retain the above copyright
10+
* notice, this list of conditions and the following disclaimer.
11+
*
12+
* * Redistributions in binary form must reproduce the above copyright
13+
* notice, this list of conditions and the following disclaimer in the
14+
* documentation and/or other materials provided with the distribution.
15+
*
16+
* * Neither the name of 'Electrostatic-Sandbox' nor the names of its contributors
17+
* may be used to endorse or promote products derived from this software
18+
* without specific prior written permission.
19+
*
20+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22+
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25+
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27+
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28+
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29+
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31+
*/
32+
33+
package electrostatic4j.snaploader.examples;
34+
35+
import java.nio.file.Files;
36+
import java.nio.file.Path;
37+
import java.nio.file.Paths;
38+
import electrostatic4j.snaploader.LibraryInfo;
39+
import electrostatic4j.snaploader.LoadingCriterion;
40+
import electrostatic4j.snaploader.NativeBinaryLoader;
41+
import electrostatic4j.snaploader.filesystem.DirectoryPath;
42+
import electrostatic4j.snaploader.platform.NativeDynamicLibrary;
43+
import electrostatic4j.snaploader.platform.util.DefaultDynamicLibraries;
44+
import electrostatic4j.snaploader.platform.util.NativeVariant;
45+
import electrostatic4j.snaploader.platform.util.PlatformPredicate;
46+
import electrostatic4j.snaploader.platform.util.PropertiesProvider;
47+
48+
/**
49+
* Tests retry exhaustion on a broken library.
50+
*
51+
* @author pavl_g.
52+
*/
53+
public class TestRetryExhaustionException {
54+
public static void main(String[] args) throws Exception {
55+
56+
final Path compressionPath = Paths.get(PropertiesProvider.USER_DIR.getSystemProperty(), "libs", "corrupted-lib.jar");
57+
final Path extractionPath = Files.createDirectories(Paths.get(PropertiesProvider.USER_DIR.getSystemProperty(), "libs",
58+
NativeVariant.OS_NAME.getProperty(), NativeVariant.OS_ARCH.getProperty()));
59+
60+
final LibraryInfo libraryInfo = new LibraryInfo(new DirectoryPath(compressionPath.toString()), new DirectoryPath("lib/placeholder"),
61+
"jmealloc", new DirectoryPath(extractionPath.toString()));
62+
63+
final NativeDynamicLibrary[] libraries = new NativeDynamicLibrary[] {
64+
DefaultDynamicLibraries.LINUX_X86_64,
65+
DefaultDynamicLibraries.LINUX_X86,
66+
new NativeDynamicLibrary("lib/windows/x86", "libjmealloc.dll", PlatformPredicate.WIN_X86),
67+
new NativeDynamicLibrary("lib/windows/x86-64", "libjmealloc.dll", PlatformPredicate.WIN_X86_64),
68+
DefaultDynamicLibraries.MAC_X86,
69+
DefaultDynamicLibraries.MAC_X86_64,
70+
};
71+
72+
final NativeBinaryLoader loader = new NativeBinaryLoader(libraryInfo);
73+
74+
loader.registerNativeLibraries(libraries).initPlatformLibrary();
75+
loader.setLoggingEnabled(true);
76+
loader.setRetryWithCleanExtraction(true);
77+
/* Native dynamic library properties */
78+
printDetails(loader);
79+
loader.loadLibrary(LoadingCriterion.INCREMENTAL_LOADING);
80+
}
81+
82+
public static void printDetails(NativeBinaryLoader loader) {
83+
System.out.println("--------------------------------------------------------------");
84+
System.out.println("OS: " + NativeVariant.OS_NAME.getProperty());
85+
System.out.println("ARCH: " + NativeVariant.OS_ARCH.getProperty());
86+
System.out.println("VM: " + NativeVariant.JVM.getProperty());
87+
System.out.println("--------------------------------------------------------------");
88+
System.out.println("Jar Path: " + loader.getNativeDynamicLibrary().getJarPath());
89+
System.out.println("Library Directory: " + loader.getNativeDynamicLibrary().getPlatformDirectory());
90+
System.out.println("Compressed library path: " + loader.getNativeDynamicLibrary().getCompressedLibrary());
91+
System.out.println("Extracted library absolute path: " + loader.getNativeDynamicLibrary().getExtractedLibrary());
92+
System.out.println("Is Extracted: " + loader.getNativeDynamicLibrary().isExtracted());
93+
System.out.println("--------------------------------------------------------------");
94+
}
95+
}

snaploader/build.gradle

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ plugins {
44
}
55

66
tasks.register("generateJavadocJar", Jar) {
7-
classifier = 'javadoc'
7+
archiveClassifier.set("javadoc")
88
from javadoc
99
}
1010

1111
tasks.register("generateSourcesJar", Jar) {
12-
classifier = 'sources'
12+
archiveClassifier.set("sources")
1313
from sourceSets.main.allSource
1414
}
1515

snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java

+21-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2023-2024, The Electrostatic-Sandbox Distributed Simulation Framework, jSnapLoader
2+
* Copyright (c) 2023-2025, The Electrostatic-Sandbox Distributed Simulation Framework, jSnapLoader
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -46,6 +46,7 @@
4646
import electrostatic4j.snaploader.library.LibraryLocator;
4747
import electrostatic4j.snaploader.platform.NativeDynamicLibrary;
4848
import electrostatic4j.snaploader.platform.util.NativeVariant;
49+
import electrostatic4j.snaploader.throwable.LoadingRetryExhaustionException;
4950
import electrostatic4j.snaploader.throwable.UnSupportedSystemError;
5051
import electrostatic4j.snaploader.util.SnapLoaderLogger;
5152

@@ -84,6 +85,10 @@ public class NativeBinaryLoader {
8485
*/
8586
protected boolean retryWithCleanExtraction;
8687

88+
protected int maxNumberOfLoadingFailure = 2;
89+
90+
protected int numberOfLoadingFailure = 0;
91+
8792
/**
8893
* Instantiates a native dynamic library loader to extract and load a system-specific native dynamic library.
8994
*/
@@ -234,12 +239,18 @@ public FileLocalizingListener getLibraryLocalizingListener() {
234239
return libraryLocalizingListener;
235240
}
236241

242+
public void setMaxNumberOfLoadingFailure(int maxNumberOfLoadingFailure) {
243+
this.maxNumberOfLoadingFailure = Math.abs(maxNumberOfLoadingFailure);
244+
}
245+
237246
/**
238247
* Loads a native binary using the platform-dependent object, for Android;
239248
* the library is loaded by its basename (variant is managed internally by the android sdk).
240249
*
241250
* @param library the platform-specific library to load
242251
* @throws IOException in case the binary to be extracted is not found on the specified jar
252+
* @throws LoadingRetryExhaustionException if the number of loading failure exceeds the specified
253+
* number.
243254
*/
244255
protected void loadBinary(NativeDynamicLibrary library) throws Exception {
245256
try {
@@ -264,10 +275,17 @@ protected void loadBinary(NativeDynamicLibrary library) throws Exception {
264275
}
265276
/* Retry with clean extract */
266277
if (isRetryWithCleanExtraction()) {
267-
cleanExtractBinary(library);
268278
if (nativeBinaryLoadingListener != null) {
269279
nativeBinaryLoadingListener.onRetryCriterionExecution(this);
270280
}
281+
// limit the number of retries to maxNumberOfLoadingFailure
282+
if (numberOfLoadingFailure >= maxNumberOfLoadingFailure) {
283+
numberOfLoadingFailure = 0; /* reset the number to zero trials */
284+
throw new LoadingRetryExhaustionException("Library loading retries exceeded the maximum!");
285+
}
286+
++numberOfLoadingFailure;
287+
// Jump call -> Possible Recursive Call
288+
cleanExtractBinary(library);
271289
}
272290
}
273291
}
@@ -281,7 +299,7 @@ protected void loadBinary(NativeDynamicLibrary library) throws Exception {
281299
*/
282300
protected void cleanExtractBinary(NativeDynamicLibrary library) throws Exception {
283301
libraryExtractor = initializeLibraryExtractor(library);
284-
SnapLoaderLogger.log(Level.INFO, getClass().getName(), "cleanExtractBinary",
302+
SnapLoaderLogger.log(Level.INFO, getClass().getName(), "cleanExtractBinary",
285303
"File extractor handler initialized!");
286304
/* CLEAR RESOURCES AND RESET OBJECTS ON-EXTRACTION */
287305
libraryExtractor.setExtractionListener(new FileExtractionListener() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright (c) 2023-2025, The Electrostatic-Sandbox Distributed Simulation Framework, jSnapLoader
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are
7+
* met:
8+
*
9+
* * Redistributions of source code must retain the above copyright
10+
* notice, this list of conditions and the following disclaimer.
11+
*
12+
* * Redistributions in binary form must reproduce the above copyright
13+
* notice, this list of conditions and the following disclaimer in the
14+
* documentation and/or other materials provided with the distribution.
15+
*
16+
* * Neither the name of 'Electrostatic-Sandbox' nor the names of its contributors
17+
* may be used to endorse or promote products derived from this software
18+
* without specific prior written permission.
19+
*
20+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22+
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25+
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27+
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28+
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29+
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31+
*/
32+
33+
package electrostatic4j.snaploader.throwable;
34+
35+
/**
36+
* Thrown to indicate that loading retries have reached their maximum.
37+
*
38+
* @author pavl_g.
39+
*/
40+
public class LoadingRetryExhaustionException extends RuntimeException {
41+
public LoadingRetryExhaustionException() {
42+
}
43+
44+
public LoadingRetryExhaustionException(String message) {
45+
super(message);
46+
}
47+
48+
public LoadingRetryExhaustionException(String message, Throwable cause) {
49+
super(message, cause);
50+
}
51+
52+
public LoadingRetryExhaustionException(Throwable cause) {
53+
super(cause);
54+
}
55+
56+
public LoadingRetryExhaustionException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
57+
super(message, cause, enableSuppression, writableStackTrace);
58+
}
59+
}

0 commit comments

Comments
 (0)