Multi-thread issue

Help
user578
2014-02-28
2015-06-18
  • user578

    user578 - 2014-02-28

    I try to use multi-threading to extract archives but get exception "SevenZipJBinding wasn't initialized successfully last time." when starting more than 1 thread.
    I tried to initialize it manually in threads but unsuccessfully. Probably there should be another way?

     
  • Boris Brodski

    Boris Brodski - 2014-03-04

    Hello,

    normally you don't need manual initialization. 7-Zip-JBinding is multithreaded library, so you can extract multiple archives in parallel. The 7-Zip-JBinding test suite tests such approach intensively, however it restricts all possible combinations of multithreaded usage to the case, where you open, query, extract and close a single archive from a same thread. For example, if you opened archive A from a thread 1 and archive B from thread 2 you call all query and extract methods of archive A from the thread 1 and all query and extract methods of archive B from the thread 2.

    This is recommended approach. In case it didn't suite your needs, please specify yours and I will add corresponding tests to the 7-Zip-JBinding test suite.

    Kind regards,
    Boris Brodski

     
  • user578

    user578 - 2014-03-21

    Thank you Boris for your help. I found the cause of this exception.

     
  • Goober5000

    Goober5000 - 2014-05-13

    Boris, and others:

    I too am using 7-Zip-JBinding in a multithreaded application, and I found out that the automatic initialization does not work well in a multithreaded environment. After some testing, I determined that it was necessary to manually initialize the library in a thread-safe manner. The following code ensures that 7-Zip-JBinding is initialized once and only once:

    private static final ObjectHolder<Boolean> isSevenZipInitialized = new ObjectHolder<Boolean>(false);
    
    /**
     * Needed because it looks like 7zip should be initialized in a thread-safe
     * manner.
     */
    public static void initSevenZip()
    {
        synchronized (isSevenZipInitialized)
        {
            boolean inited = isSevenZipInitialized.get();
            if (inited)
                return;
            isSevenZipInitialized.set(true);
    
            try
            {
                SevenZip.initSevenZipFromPlatformJAR();
                logger.info("7zip initialized successfully!");
            }
            catch (SevenZipNativeInitializationException sznie)
            {
                logger.error("Unable to initialize 7zip!", sznie);
            }
        }
    }
    

    I added this code to a utility class in my application, and I ensured that my code always called MiscUtils.initSevenZip() before extracting a file. With this change, everything works successfully. My code can now extract multiple files in multiple parallel threads (archive A in thread 1, archive B in thread 2, etc.) without any conflict.

     
  • Steve

    Steve - 2015-06-18

    I have encountered the same problem in a multithreaded application, and had to resort to a method similar to Goober5000. I believe the problem is that the SevenZip.initSevenZipFromPlatformJARIntern() method is not thread safe. It should be employing a double-checked locking pattern and the boolean flags that it uses to track initialization need to be marked as volatile.

    Example:

    private static volatile boolean autoInitializationWillOccur = true;
    private static volatile boolean initializationSuccessful = false;
    private static volatile SevenZipNativeInitializationException lastInitializationException = null;
    private static volatile List<String> availablePlatforms = null;
    private static volatile String usedPlatform = null;
    private static volatile File[] temporaryArtifacts = null;
    
    ....
    
    private static void initSevenZipFromPlatformJARIntern(String platform, File tmpDirectory)
        throws SevenZipNativeInitializationException {
    
        autoInitializationWillOccur = false;
        if (initializationSuccessful) {
            // Native library was already initialized successfully. No need for further initialization.
            return;
        }
        synchronized (SevenZip.class) {
            //double-checked lock
            if (initializationSuccessful) {
                return;
            }
            try {   
                determineAndSetUsedPlatform(platform);
                Properties properties = loadSevenZipJBindingLibProperties();
                File tmpDirFile = createOrVerifyTmpDir(tmpDirectory);
                File sevenZipJBindingTmpDir = getOrCreateSevenZipJBindingTmpDir(tmpDirFile, properties);
                List<File> nativeLibraries = copyOrSkipLibraries(properties, sevenZipJBindingTmpDir);
                loadNativeLibraries(nativeLibraries);
                nativeInitialization();
            } catch (SevenZipNativeInitializationException sevenZipNativeInitializationException) {
                lastInitializationException = sevenZipNativeInitializationException;
                throw sevenZipNativeInitializationException;
            }
        }
    
    }
    
     

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks