Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Application cannot start for exception 'zip file closed' #32042

Closed
pj892031 opened this issue Aug 9, 2022 · 3 comments
Closed

Application cannot start for exception 'zip file closed' #32042

pj892031 opened this issue Aug 9, 2022 · 3 comments
Assignees
Labels
status: duplicate A duplicate of another issue

Comments

@pj892031
Copy link

pj892031 commented Aug 9, 2022

Our application is split into two JARs (The first contains the spring boot launcher and our classes. The second file contains just 3rd party libraries) to be possible to share libraries between multiple applications to mitigate data transfer etc.:

jar lite.jar:

+BOOT-INF
| + classes (our classes and resources)
| + lib (our libraries - not the 3rd party)
| + classpath.idx
| + layers.idx
+ META-INF
| + MANIFEST.MF
+ org (spring boot launcher)

jar lite-lib.jar

+ BOOT-INF
| + lib (3rd party libraries)
+ META-INF
  + MANIFEST.MF (empty manifest)

We run this application with command like java -cp lite.jar -Dloader.path=lite-lib.jar org.springframework.boot.loader.PropertiesLauncher

Our JDK:

java version "1.8.0_321"
Java(TM) SE Runtime Environment (build 8.0.7.5 - pmz6480sr7fp5-20220208_01(SR7 FP5))
IBM J9 VM (build 2.9, JRE 1.8.0 z/OS s390x-64-Bit Compressed References 20220104_19630 (JIT enabled, AOT enabled)
OpenJ9   - 2d4c7d9
OMR      - 59845b7
IBM      - 3c151c1)
JCL - 20220120_01 based on Oracle jdk8u321-b07

Since version 2.6.9 we randomly got this exception:

java.lang.reflect.InvocationTargetException
.at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
.at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:90)
.at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
.at java.lang.reflect.Method.invoke(Method.java:508)
.at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
.at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
.at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
.at org.springframework.boot.loader.PropertiesLauncher.main(PropertiesLauncher.java:467)
Caused by: java.lang.IllegalStateException: zip file closed
.at org.springframework.boot.loader.jar.JarFile.ensureOpen(JarFile.java:383)
.at org.springframework.boot.loader.jar.JarFile.getEntry(JarFile.java:269)
.at org.springframework.boot.loader.jar.JarFileWrapper.getEntry(JarFileWrapper.java:82)
.at org.springframework.boot.loader.LaunchedURLClassLoader.lambda$definePackage$0(LaunchedURLClassLoader.java:225)
.at org.springframework.boot.loader.LaunchedURLClassLoader$$Lambda$10/0x00000000d8525970.run(Unknown Source)
.at java.security.AccessController.doPrivileged(AccessController.java:774)
.at org.springframework.boot.loader.LaunchedURLClassLoader.definePackage(LaunchedURLClassLoader.java:217)
.at org.springframework.boot.loader.LaunchedURLClassLoader.definePackageIfNecessary(LaunchedURLClassLoader.java:199)
.at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:140)
.at java.lang.ClassLoader.loadClass(ClassLoader.java:873)
....
.at ch.qos.logback.classic.spi.TurboFilterList.getTurboFilterChainDecision(TurboFilterList.java:60)
.at ch.qos.logback.classic.LoggerContext.getTurboFilterChainDecision_0_3OrMore(LoggerContext.java:269)
.at ch.qos.logback.classic.Logger.filterAndLog_0_Or3Plus(Logger.java:373)
.at ch.qos.logback.classic.Logger.error(Logger.java:522)
....

It seems that the reason is the commit b42f056:

It collects references of nested JARs and then closes their streams if the main is closing, see:

private final List<JarFile> nestedJars = Collections.synchronizedList(new ArrayList<>());

private JarFile createJarFileFromFileEntry(JarEntry entry) throws IOException {
if (entry.getMethod() != ZipEntry.STORED) {
throw new IllegalStateException(
"Unable to open nested entry '" + entry.getName() + "'. It has been compressed and nested "
+ "jar files must be stored without compression. Please check the "
+ "mechanism used to create your executable jar file");
}
RandomAccessData entryData = this.entries.getEntryData(entry.getName());
JarFile nestedJar = new JarFile(this.rootFile, this.pathFromRoot + "!/" + entry.getName(), entryData,
JarFileType.NESTED_JAR);
this.nestedJars.add(nestedJar);
return nestedJar;
}

public void close() throws IOException {
if (this.closed) {
return;
}
synchronized (this) {
super.close();
if (this.type == JarFileType.DIRECT) {
this.rootFile.close();
}
if (this.wrapper != null) {
this.wrapper.close();
}
for (JarFile nestedJar : this.nestedJars) {
nestedJar.close();
}
this.closed = true;
}
}

I guess the problem is in synchronization between threads. The code contains synchronization blocks for elementary operation, but cannot detect if a different thread is trying to read data meanwhile.

Once I remove this part of the code (closing of nestedJar) I was not able to simulate this case again.

If I am right, those streams shouldn't be closed. One way could be to use ie. ByteArrayInputStream as a buffer and takes care just of the input streams reading the data.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Aug 9, 2022
@wilkinsona wilkinsona added type: regression A regression from a previous release and removed status: waiting-for-triage An issue we've not yet triaged labels Aug 10, 2022
@wilkinsona wilkinsona added this to the 2.6.x milestone Aug 10, 2022
@wilkinsona
Copy link
Member

This may be a duplicate of #31853.

@philwebb
Copy link
Member

Having dug into #31853 a bit more I'm pretty sure this is a duplicate. @pj892031 If at all possible, once build 1110 if green, could you try the latest SNAPSHOT build and see if the issue is fixed?

@philwebb philwebb closed this as not planned Won't fix, can't repro, duplicate, stale Aug 16, 2022
@philwebb philwebb added status: duplicate A duplicate of another issue and removed type: regression A regression from a previous release labels Aug 16, 2022
@philwebb philwebb removed this from the 2.6.x milestone Aug 16, 2022
@pj892031
Copy link
Author

I tested that with the snapshot version and could not reproduce the bug. It seems to be solved. Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: duplicate A duplicate of another issue
Projects
None yet
Development

No branches or pull requests

4 participants