Skip to content

OneModuleClassLoader / JarClassLoader doesnt load versioned classess in MR (Multi-Release) jars #9371

@priyanahata

Description

@priyanahata

Apache NetBeans version

Apache NetBeans 29

What happened

JarClassLoader has some Multi-Release logic (lines 622-637). However, there are two fatal flaws in its implementation:

The Constructor Bug: Look at line 568: ret = new JarFile(file, false); It uses the old Java 8 constructor. It does not use the modern new JarFile(file, verify, mode, Runtime.version()). Without that version parameter, the JarFile object itself operates in "Legacy Mode," meaning its internal index doesn't automatically map versioned entries to their base names.

The "New Package" Blind Spot: NetBeans uses a "Covered Packages" index to speed up loading. In listCoveredPackages (line 714), it iterates through the JAR entries. Since the JAR wasn't opened in MR-mode, it sees META-INF/versions/22/org/lwjgl/... as just a random file under META-INF. It does not realize this represents the package org.lwjgl.system.ffm.

The Result: If a package (like ffm) only exists in the versioned folder, NetBeans never adds it to the "Covered Packages" list, and the classloader never even attempts to load it.

Conclusion: Your intuition was 100% correct. NetBeans' MR support is a "half-bridge" that only works for overriding existing classes, but completely fails for the modern "Add-on" packages used by LWJGL.

Language / Project Type / NetBeans Component

NBM maven project

How to reproduce

Try adding LWJGL 3.4.1 as a dependency and then try to initialize the lib with glfwInit(). There is a class there called FFM that is only supposed to be visible for JDK25 because it is in META-INF/versions/25/FMM.class but the JarClassLoader doesn't see it

Did this work correctly in an earlier version?

No / Don't know

Operating System

ubuntu 24

JDK

Temurin 25

Apache NetBeans packaging

Apache NetBeans binary zip, Community provided installer

Anything else

No response

Are you willing to submit a pull request?

No, but the AI generated patch is this:


--- org/netbeans/JarClassLoader.java
+++ org/netbeans/JarClassLoader.java
@@ -565,7 +565,11 @@
                                         long now = System.currentTimeMillis();
                                         JarFile ret;
                                         try {
-                                            ret = new JarFile(file, false);
+                                            if (RUNTIME_VERSION > BASE_VERSION) {
+                                                ret = new JarFile(file, false, ZipFile.OPEN_READ, Runtime.version());
+                                            } else {
+                                                ret = new JarFile(file, false);
+                                            }
                                         } catch (FileNotFoundException | NoSuchFileException ex) {
                                             throw (ZipException)new ZipException(ex.getMessage()).initCause(ex);
                                         }
@@ -734,6 +738,15 @@
                             if (known.add(res)) save.append(res).append(',');
                             continue;
                         }
+                        
+                        // MR-JAR Support: Handle versioned entries
+                        if (itm.startsWith(META_INF + "versions/")) {
+                            int thirdSlash = itm.indexOf('/', META_INF.length() + 9); // Skip META-INF/versions/NN/
+                            if (thirdSlash != -1) {
+                                itm = itm.substring(thirdSlash + 1);
+                                slash = itm.lastIndexOf('/');
+                            }
+                        }
+
                         String pkg = slash > 0 ? itm.substring(0, slash).replace('/','.') : "";
                         if (known.add(pkg)) save.append(pkg).append(',');
                     }

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind:bugBug report or fixneeds:triageRequires attention from one of the committers

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions