<div dir="ltr"><div dir="ltr">On Sun, Sep 22, 2024 at 6:46 PM Rafael Winterhalter <<a href="mailto:rafael.wth@gmail.com">rafael.wth@gmail.com</a>> wrote:<br></div><div class="gmail_quote"><div><br></div><div>Sorry, still not sure I understand the scenario.. <br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">That is only true for Class::getResource which resolves resources relative to the loaded class's class file location. <br></blockquote><div><br></div><div>Class:getResource simply adds the package name prefix and calls ClassLoader::getResource. It has no separate knowledge about the class file's location.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>When loading a class, ClassLoader::findClass respects the multi-release characteristic. But for ClassLoader::getResource, this is not the case.</div></div></blockquote><div><br></div><div>ClassLoader as such has no concept of multi-release JAR files, that's entirely up to the class loader implementation. In OpenJDK, this is supported by URLClassLoader, or rather URLClassPath.JarLoader::getResource, which calls JarFile::getEntry which is where the version lookup happens.</div><div><br></div><div>If you have a class loader which respects multi-release characteristics in ClassLoader::loadClass, but not in ClassLoader::getResource, then that is a strange way to implement a class loader.</div><div><br></div><div>Is there some intricacy of class loader hierarchies that I'm missing here?</div><div><br></div><div>The following unit test demonstrates how URLClassLoader::getResource resolves versions:</div><div><br></div><div>@Test<br>public void getVersionedClass() throws IOException {<br>    Path zip = Path.of("multi.zip");<br>    Manifest man = new Manifest();<br>    Attributes attrs = man.getMainAttributes();<br>    attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0");<br>    attrs.put(Attributes.Name.MULTI_RELEASE, "true");<br>    try (JarOutputStream jo = new JarOutputStream(Files.newOutputStream(zip), man)) {<br>        jo.putNextEntry(new ZipEntry("META-INF/versions/21/com/example/HelloWorld.class"));<br>        jo.putNextEntry(new ZipEntry("com/example/HelloWorld.class"));<br>    }<br>    ClassLoader loader = new URLClassLoader(new URL[] {zip.toUri().toURL()});<br>    URL resource = loader.getResource("com/example/HelloWorld.class");<br>    String path = resource.getFile().substring(resource.getFile().indexOf("!/") + 2);<br>    assertEquals("META-INF/versions/21/com/example/HelloWorld.class", path);<br>}<br></div><div><br></div><div>   </div></div></div>