一、问题
最近在开发过程中遇到一个问题,使用sevenzipjbinding解压文件报 SevenZipJBinding wasn’t initialized successfully last 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);
}
}
}
二、原因
查看sevenzipjbinding源码发现,在调用解压方法的时候,先判断是否需要进行初始化, autoInitializationWillOccur 默认为true,当第一个线程进来此方法时,将autoInitializationWillOccur修改为false,然后初始化相关依赖(此操作需要一定的耗时),此时其他线程进来此方法,autoInitializationWillOccur已经变为false 就不再进行初始化,但是由于第一个线程还没有完成初始化操作initializationSuccessful还是为false,所以就会抛出SevenZipJBinding wasn’t initialized successfully last time异常
三、解决
使用ApplicationRunner在程序启动完成后,自动执行一下initSevenZipFromPlatformJAR方法,先将sevenzipjbinding需要的依赖完成初始化。
@Component
public class InitService implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
SevenZip.initSevenZipFromPlatformJAR();
log.info("初始化sevenzipjbinding相关依赖完成!");
}
}