<div dir="auto"><div>When the ClassLoader API is used in build plugins, this often serves as a fallback to non-standardized class storage where the retrieval implementation is bound to the ClassLoder API. I would have to guess but I would not assume that many of them use a JarInputStream as a backing mechanism. By my experience, custom class loaders typically load classes via TCP.</div><div dir="auto"><br></div><div dir="auto">One use case I remember is a class loader that queried a server which loaded jars via a URLClassLoader and served class files on demand. In such a case, it would also be relevant that the resource would be consistent with the client JVM version, not the server one. Updating the server alone would result in different resources. Of course, using JarFile to access resources would be the better option here, but ideally one could adapt MR jars without larger rewrites. URLClassLoder accepts URLs while JarFile requires File, what might result in a non-trivial rewrite, for example if there's multiple hoops.</div><div dir="auto"><br></div><div dir="auto">I don't think this is a large issue either, rather an edge case, otherwise I would have stumbled over this earlier. The main issue is that Java 8 always allows me to access META-INF resources and the original class file via the ClassLoder API. Starting from Java 9, the original class file might be shadowed and inaccessible. So a build might yield a different result after updating the JDK, and currently I do not see a way to resolve this backwards compatible. Therefore I was wondering if a new API should adress this. In JarFile, you can iterate over all resources, including those that are shadowed, at least. It is something like that that I am looking for.</div><div dir="auto"><br></div><div dir="auto">As for a public issue: I recently had an unrelated issue on MR JARs in builds what made me aware of this possibility of encountering MR jar files through ClassLoader class file locators in build plugins, which is a combination of two rare events that nobody complained about before. But I could not point you to an old ticket.</div><div dir="auto"><br><div class="gmail_quote" dir="auto"><div dir="ltr" class="gmail_attr">Eirik Bjørsnøs <<a href="mailto:eirbjo@gmail.com">eirbjo@gmail.com</a>> schrieb am Di., 24. Sept. 2024, 13:44:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div dir="ltr">On Tue, Sep 24, 2024 at 12:44 PM Rafael Winterhalter <<a href="mailto:rafael.wth@gmail.com" target="_blank" rel="noreferrer">rafael.wth@gmail.com</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><p dir="ltr">Without getting lost in specifics:</p></blockquote><div>It is also possible to get very lost by lacking specifics :-)</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<p dir="ltr">If the build plugin now wants to create instrumented versions of class files for a Java 17 JVM, while the build is run on a Java 21 JVM, I can support this for JAR files, for folders, but I cannot fetch the adequate resource when the underlying resource accessor is a class loader. I do not think that I can work around this, or do I overlook something?</p></blockquote><div>Thanks, this narrows down your use case considerably and also explains why you would be interested in loading resources of versions different than the runtime version.</div><div><br></div><div>Does the class loader in question return JAR-form URLs? If that's the case, you could use JarURLConnection.getJarFile() and use getInputStream to get the versioned resource of choice:</div><div><br></div><span style="font-family:monospace">ClassLoader loader = new URLClassLoader(new URL[] {zip.toUri().toURL()});</span><br style="font-family:monospace"><span style="font-family:monospace">URL resource = loader.getResource(baseName);</span><br style="font-family:monospace"><span style="font-family:monospace">if (resource.openConnection() instanceof JarURLConnection con) {</span><br style="font-family:monospace"><span style="font-family:monospace">    try (var is = con.getJarFile().</span><span style="font-family:monospace">getInputStream(new ZipEntry(baseName))) {</span><br style="font-family:monospace"><span style="font-family:monospace">        assertArrayEquals("base".</span><span style="font-family:monospace">getBytes(StandardCharsets.UTF_</span><span style="font-family:monospace">8),</span><br style="font-family:monospace"><span style="font-family:monospace">                is.readAllBytes());</span><br style="font-family:monospace"><span style="font-family:monospace">    }</span><br style="font-family:monospace"><div><span style="font-family:monospace">}</span></div><div><br></div><div>Or just parse the URL to find the path to the JAR file and open it using ZipFile/JarFile APIs.</div><div><br></div><div>Is the issue reported to Byte Buffy publicly available?</div><div><br></div><div>Thanks,</div><div>Eirik. </div></div></div>
</blockquote></div></div></div>