Skip to content

Commit d1e355d

Browse files
committed
NativeBinaryLoader: library localizing and extracting optimizations against memory leaks and enabled external app binding to API lifecycle
1 parent 0475893 commit d1e355d

File tree

1 file changed

+89
-7
lines changed

1 file changed

+89
-7
lines changed

snaploader/src/main/java/electrostatic/snaploader/NativeBinaryLoader.java

Lines changed: 89 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,12 @@
3838
import java.util.logging.Level;
3939
import java.util.logging.Logger;
4040
import java.lang.UnsatisfiedLinkError;
41-
import electrostatic.snaploader.filesystem.ExtractionListener;
41+
import electrostatic.snaploader.filesystem.FileExtractionListener;
4242
import electrostatic.snaploader.filesystem.FileExtractor;
43+
import electrostatic.snaploader.filesystem.FileLocalizingListener;
4344
import electrostatic.snaploader.filesystem.FileLocator;
4445
import electrostatic.snaploader.library.LibraryExtractor;
46+
import electrostatic.snaploader.library.LibraryLocator;
4547
import electrostatic.snaploader.platform.NativeDynamicLibrary;
4648
import electrostatic.snaploader.platform.util.NativeVariant;
4749

@@ -66,6 +68,10 @@ public class NativeBinaryLoader {
6668

6769
protected SystemDetectionListener systemDetectionListener;
6870

71+
protected FileLocalizingListener libraryLocalizingListener;
72+
73+
protected FileExtractionListener libraryExtractionListener;
74+
6975
/**
7076
* An Output stream concrete provider for library extraction.
7177
*/
@@ -221,14 +227,30 @@ public NativeBinaryLoadingListener getNativeBinaryLoadingListener() {
221227
return nativeBinaryLoadingListener;
222228
}
223229

224-
public void setSystemFoundListener(SystemDetectionListener systemDetectionListener) {
230+
public void setSystemDetectionListener(SystemDetectionListener systemDetectionListener) {
225231
this.systemDetectionListener = systemDetectionListener;
226232
}
227233

228-
public SystemDetectionListener getSystemFoundListener() {
234+
public SystemDetectionListener getSystemDetectionListener() {
229235
return systemDetectionListener;
230236
}
231237

238+
public void setLibraryExtractionListener(FileExtractionListener libraryExtractionListener) {
239+
this.libraryExtractionListener = libraryExtractionListener;
240+
}
241+
242+
public FileExtractionListener getLibraryExtractionListener() {
243+
return libraryExtractionListener;
244+
}
245+
246+
public void setLibraryLocalizingListener(FileLocalizingListener libraryLocalizingListener) {
247+
this.libraryLocalizingListener = libraryLocalizingListener;
248+
}
249+
250+
public FileLocalizingListener getLibraryLocalizingListener() {
251+
return libraryLocalizingListener;
252+
}
253+
232254
/**
233255
* Loads a native binary using the platform dependent object, for android,
234256
* the library is loaded by its basename (variant is managed internally by the android sdk).
@@ -272,24 +294,39 @@ protected void loadBinary(NativeDynamicLibrary library) throws IOException {
272294
*/
273295
protected void cleanExtractBinary(NativeDynamicLibrary library) throws IOException {
274296
libraryExtractor = initializeLibraryExtractor(library);
297+
log(Level.INFO, "cleanExtractBinary", "File extractor handler initialized!", null);
275298
/* CLEAR RESOURCES AND RESET OBJECTS ON-EXTRACTION */
276-
libraryExtractor.setExtractionListener(new ExtractionListener() {
299+
libraryExtractor.setExtractionListener(new FileExtractionListener() {
277300
@Override
278301
public void onExtractionCompleted(FileExtractor fileExtractor) {
279302
try {
303+
// free resources
304+
// removes file locks on some OS
280305
libraryExtractor.getFileLocator().close();
281306
libraryExtractor.close();
282307
libraryExtractor = null;
283308
log(Level.INFO, "cleanExtractBinary", "Extracted successfully to " + library.getExtractedLibrary(), null);
309+
log(Level.INFO, "cleanExtractBinary", "Filesystem Resources closed!", null);
310+
// load the native binary
284311
loadBinary(library);
285312
} catch (Exception e) {
286313
log(Level.SEVERE, "cleanExtractBinary", "Error while loading the binary!", e);
287314
}
315+
316+
// bind the extraction lifecycle to the user application
317+
if (libraryExtractionListener != null) {
318+
libraryExtractionListener.onExtractionCompleted(fileExtractor);
319+
}
288320
}
289321

290322
@Override
291323
public void onExtractionFailure(FileExtractor fileExtractor, Throwable throwable) {
292324
log(Level.SEVERE, "cleanExtractBinary", "Extraction has failed!", throwable);
325+
326+
// bind the extraction lifecycle to the user application
327+
if (libraryExtractionListener != null) {
328+
libraryExtractionListener.onExtractionFailure(fileExtractor, throwable);
329+
}
293330
}
294331

295332
@Override
@@ -298,31 +335,76 @@ public void onExtractionFinalization(FileExtractor fileExtractor, FileLocator fi
298335
if (fileLocator != null &&
299336
fileLocator.getFileInputStream() != null) {
300337
fileLocator.close();
338+
log(Level.INFO, "cleanExtractBinary", "File locator Resources closed!", null);
301339
}
302340
if (fileExtractor != null &&
303341
fileExtractor.getFileOutputStream() != null) {
304342
fileExtractor.close();
343+
log(Level.INFO, "cleanExtractBinary", "File extractor Resources closed!", null);
305344
}
306345
} catch (IOException e) {
307346
log(Level.SEVERE, "cleanExtractBinary", "Error while closing the resources!", e);
308347
}
348+
349+
// bind the extraction lifecycle to the user application
350+
if (libraryExtractionListener != null) {
351+
libraryExtractionListener.onExtractionFinalization(fileExtractor, fileLocator);
352+
}
309353
}
310354
});
311355
libraryExtractor.extract();
312356
}
313357

314358
/**
315-
* Initializes a filesystem extrator object if the filesystem extractor object associated with this loader isnot defined.
359+
* Initializes a filesystem extractor object
360+
* if the filesystem extractor object associated with this loader isn't defined.
316361
*
317362
* @param library the native dynamic library to load
318363
* @return a new FileExtractor object that represents an output stream provider
319364
* @throws IOException if the jar filesystem to be located is not found, or if the extraction destination is not found
320365
*/
321366
protected FileExtractor initializeLibraryExtractor(NativeDynamicLibrary library) throws IOException {
367+
FileExtractor extractor;
322368
if (library.getJarPath() != null) {
323-
return new LibraryExtractor(library.getJarPath(), library.getCompressedLibrary(), library.getExtractedLibrary());
369+
extractor = new LibraryExtractor(library.getJarPath(), library.getCompressedLibrary(), library.getExtractedLibrary());
370+
} else {
371+
extractor = new LibraryExtractor(library.getCompressedLibrary(), library.getExtractedLibrary());
324372
}
325-
return new LibraryExtractor(library.getCompressedLibrary(), library.getExtractedLibrary());
373+
final LibraryLocator fileLocator = preInitLibraryLocator(extractor);
374+
fileLocator.initializeLocator();
375+
return extractor;
376+
}
377+
378+
protected LibraryLocator preInitLibraryLocator(FileExtractor extractor) {
379+
extractor.getFileLocator().setFileLocalizingListener(new FileLocalizingListener() {
380+
@Override
381+
public void onFileLocalizationSuccess(FileLocator locator) {
382+
log(Level.INFO, "initializeLibraryExtractor", "Locating native libraries has succeeded!", null);
383+
384+
// bind the library locator lifecycle to the user application
385+
if (libraryLocalizingListener != null) {
386+
libraryLocalizingListener.onFileLocalizationSuccess(locator);
387+
}
388+
}
389+
390+
@Override
391+
public void onFileLocalizationFailure(FileLocator locator, Throwable throwable) {
392+
log(Level.SEVERE, "initializeLibraryExtractor", "Locating native libraries has failed!", throwable);
393+
try {
394+
extractor.close();
395+
locator.close();
396+
log(Level.INFO, "initializeLibraryExtractor", "Filesystem resources closed!", null);
397+
} catch (IOException e) {
398+
log(Level.SEVERE, "initializeLibraryExtractor", "File locator closure failed!", e);
399+
}
400+
401+
// bind the library locator lifecycle to the user application
402+
if (libraryLocalizingListener != null) {
403+
libraryLocalizingListener.onFileLocalizationFailure(locator, throwable);
404+
}
405+
}
406+
});
407+
return (LibraryLocator) extractor.getFileLocator();
326408
}
327409

328410
/**

0 commit comments

Comments
 (0)