Tag Archives: RAR Files Extract Error

How to Solve RAR Files Extract Error with sevenzipjbinding (Multithread Processing)

1. Question

Recently, I encountered a problem in the development process. Use sevenzipjbinding to extract the file and report error: SevenZipJBinding wasn’t initialized successfully last time

Use a simple case to repeat it. Note: after the program is started for the first time, the decompression method will appear when multiple threads execute decompression at the same time

@RestController
@RequestMapping("/test")
@Slf4j
public class TestContortller {

    @GetMapping("/unRar")
    public void unRar() {
        String source = "D:\\temp\\test.rar";
        String target = "D:\\temp\\test\\";
        new Thread(() -> unRar(source, target + Thread.currentThread().getId())).start();
        new Thread(() -> unRar(source, target + Thread.currentThread().getId())).start();
        new Thread(() -> unRar(source, target + Thread.currentThread().getId())).start();
    }

    public static void unRar(String source, String target) {
        try (RandomAccessFile randomAccessFile = new RandomAccessFile(source, "r");
             IInArchive archive = SevenZip.openInArchive(null, new RandomAccessFileInStream(randomAccessFile))) {
            int[] in = new int[archive.getNumberOfItems()];
            for (int i = 0; i < in.length; i++) {
                in[i] = i;
            }
            archive.extract(in, false, new ExtractCallback(archive, target));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }
}

2. Cause

Checking the sevenzipjbinding source code, we find that when calling the decompression method, we first determine whether initialization is needed. autoInitializationWillOccur defaults to true, and when the first thread comes into this method, autoInitializationWillOccur is changed to When the first thread comes in this method, autoInitializationWillOccur will be changed to false, and then initialize the relevant dependencies (this operation takes some time), at this time other threads come in this method, autoInitializationWillOccur has changed to false and no longer initialize, but because the first thread has not completed the initialization operation initializationSuccessful is still is false, so it will throw the SevenZipJBinding wasn’t initialized successfully last time exception

3. Solution

You can use ApplicationRunner to automatically execute the initSevenZipFromPlatformJAR method after the program is started, to first initialize the dependencies needed for sevenzipjbinding.

@Component
public class InitService implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        SevenZip.initSevenZipFromPlatformJAR();
        log.info("Initialize sevenzipjbinding related dependencies complete!");
    }
}