Our current nested jar support is pretty complicated due to support for earlier versions of Java. There are also a lot of bugs that we're unable to fix with the current implementation. Rewriting our implementation would help us a great deal going forward.

Comment From: philwebb

Reopening due to Windows build issues:

java.io.IOException: Failed to delete temp directory C:\Windows\TEMP\junit17935825065843241783. The following paths could not be deleted (see suppressed exceptions for details): , test.jar

Comment From: philwebb

The Windows build is now fixed.

Comment From: harveycggit

Hi, I was using org.springframework.boot.loader.jar.JarFile to access nested jars so I could do some introspection, etc. The class has been removed. Can you advise what replaces it?

ApplicationHome home = new ApplicationHome(SomeClassOfMine.class);
JarFile JarFile = new JarFile(home.getSource())
Enumeration<JarEntry> jarEntries =  jarFile.entries();
while (jarEntries.hasMoreElements()) {
// bunch of code omitted
     boolean isJar = jarEntry.getName().endsWith(".jar");
     // recurse to get get any further nested entries
     if (isJar) {
               classesFromSpringFatJar(jarFile.getNestedJarFile(jarEntry), upennClassesFromfatJar, packageName);
        }
}

etc etc.

What I need it a handle to all of the jars.

Thanks! Charles Harvey

Comment From: philwebb

@harveycggit

The new class you want to use is probably org.springframework.boot.loader.jar.NestedJarFile. You can do new NestedJarFile(home.getSource(), jarEntry.getName()).

Comment From: harveycggit

Thank you so much for the quick response @philwebb ! So I can use new NestedJarFile(home.getSource(), jarEntry.getName()) even if the JarEntry is nested in a chain of jars inside home.getSource()? It is unclear to me whether ZipContent.open behaves in a recursive fashion.

Comment From: philwebb

@harveycggit Nesting can only be one level deep. You can't have a nested jar inside a nested jar, you can only have a nested jar inside a regular jar.

Comment From: harveycggit

@philwebb thank you again for the response. The NestedJarFileConstructor says it will take null for a resource name:

/**
 * Creates a new {@link NestedJarFile} instance to read from the specific
 * {@code File}.
 * @param file the jar file to be opened for reading
 * @param nestedEntryName the nested entry name to open or {@code null}
 * @throws IOException on I/O error
 */
public NestedJarFile(File file, String nestedEntryName) throws IOException {
    this(file, nestedEntryName, null, true, Cleaner.instance);
}

However, it then calls a constructor that throws the following error if you pass null: if (onlyNestedJars && (nestedEntryName == null || nestedEntryName.isEmpty())) { throw new IllegalArgumentException("nestedEntryName must not be empty"); }

So, when I am initially loading the resources I am not looking for a particular entry; I need to iterate through all jars and look for classes that implement some interfaces and so on. What should I be passing with the initial load?

new NestedJarFile(home.getSource(), ???)

Thanks again! Charles

Comment From: philwebb

That's a mistake in the Javadoc I think. I originally supported null but then changed my mind about it. I'd recommend using the regular JDK JarFile class for non-nested jars. I've opened #39252 to fix the docs.

Comment From: qsLI

Do you have any performance test data?