JDK-6957241 : ClassLoader.getResources() returns only 1 instance when using jar indexing
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang:class_loading
  • Affected Version: 6u10,18
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: generic
  • CPU: generic
  • Submitted: 2010-05-31
  • Updated: 2021-12-03
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbdUnresolved
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
Java HotSpot(TM) Client VM (build 16.3-b01, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
I have a resource file (named resource.txt) that is located in 2 jar files (jar1.jar and mainJar.jar).
mainJar.jar depends on jar1.jar (I have a classpath entry in the manifest).

When I try to load the resource from mainJar using ClassLoader.getResources() I get 2 results => GOOD

Now I generate the INDEX.LIST using jar -i mainJar.jar.

Running the same test again, I now have only 1 result => BAD

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create 2 JARs with the given index in the main JAR:

JarIndex-Version: 1.0

mainJarWithIndex.jar
Main.class
resource.txt

jar1.jar
resource.txt

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Resource found = 2
ACTUAL -
Resource found = 1

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class Main {

    public static void main(String[] args) throws IOException {
        Enumeration<URL> e = Main.class.getClassLoader().getResources("resource.txt");
        int count = 0;
        while (e.hasMoreElements()) {
            URL u = e.nextElement();
            count ++;
        }
        System.out.println("Resource found = " + count);
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Do not generate INDEX.LIST but it will produce bad performances when using webstart or applet.

Comments
(tangent) Modular jars indeed offer a great performance improvement, but only by taking advantage of a large constraint - no split packages - which allow the module system to build a map of package to jar file at runtime. Google's build tools (e.g. bazel) by design encourages the creation of split packages, so migrating to modular jars for the performance advantages is likely to be a very expensive future migration.
07-09-2021

Indeed, there may be tools that change the contents of a JAR file that don't know about the index (although that would be a bug in those tools). I had hoped to deprecate JAR index support in JDK 9 but there was too much to do. The index is not used (ignored) by modular JARs. It may or may not work correctly in all cases with Multi-Release JARs. Now seems a good time to re-visit all this.
03-09-2021

The JAR indexing mechanism has not seen much maintenance by jar/zip maintainers, including myself. I once considered using it, but never did, and have always shied away from mechanisms that make jar files more brittle in the sense of being breakable by zip tools that are not aware of the index.
03-09-2021

I also agree that it's time to consider removing the JAR index mechansim, which is legacy and originally for applets [1]. [1] https://docs.oracle.com/en/java/javase/16/docs/specs/jar/jar.html#jar-index
01-09-2021

The JAR indexing mechanism is legacy, maybe it's time to finally remove it.
01-09-2021

This bug still happen in jdk master and is a generic problem.
30-08-2021