JEP 330 class loader getResourceAsStream

Peter Levart peter.levart at gmail.com
Mon Aug 27 17:51:46 UTC 2018



On 08/27/2018 04:47 PM, David Lloyd wrote:
> On Mon, Aug 27, 2018 at 9:41 AM Alan Bateman <Alan.Bateman at oracle.com> wrote:
>> On 24/08/2018 18:27, David Lloyd wrote:
>>> Why not go ahead and implement getResource as well?  It's not *that*
>>> big of a deal to add a URL handler, and it would be a fairly trivial
>>> one.
>> Right, it wouldn't be too hard but it would require a bit of plumbing to
>> have it backed by the Memory* classes in the source file launcher. That
>> said, a newbie starting out with "java HelloWorld.java" is unlikely to
>> be writing code that needs the class bytes so it's more likely the more
>> advanced cases where the code is using a library that needs the bytes.
> AFAIK any code would expect that resources available as streams would
> generally also be available as URLs.  I'm not sure that distinguishing
> between basic and advanced code really clarifies anything in terms of
> the question.
>

Maybe there's a middle ground where URLStreamHandlerProvider is not 
provided. In other words, one would not be able to "parse" URL(s) from 
String(s) such that those URL(s) would be usable in providing the 
content via openConnection().getInputStream(). Such a thing would be 
very hard to achieve anyway as one can think of situations where there's 
more than one MemoryClassLoader instance present in a single JVM (for 
example, some java source launched via java launcher uses tools API to 
instruct "java" tool to launch another java source file). In such 
situation one would have to distinguish URL(s) resolving resources of 
one MemoryClassLoader from URL(s) resolving resources of another 
MemoryClassLoader. In other words, URL scheme would have to contain some 
identification of MemoryClassLoader instance and MemoryClassLoader 
instances would have to be registered in a JVM global Map<UUID, 
WeakReference<MemoryClassLoader>> for example, etc, etc... Just imagine 
the complexity of a full-blown solution.

There's a middle ground where MemoryClassLoader.getResource() returns a 
URL which is usable in providing the content such that 
url.openConnection() returns an URLConnection and such 
urlConnection.getInputStream() returns an InputStream providing the 
class bytes. One can even construct URL(s) by providing some URL 
obtained by getResource() and resolving against it, effectively 
targeting the choosen MemoryClassLoader instance. Here's such prototype 
for illustration:

http://cr.openjdk.java.net/~plevart/jdk-dev/MemoryClassLoader_getResource/webrev.01/

Running: java Test.java with the following source:


import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

public class Test {
     public static void main(String[] args) throws Exception {
         String name = Test.class.getName().replace('.', '/') + ".class";
         URL url = Test.class.getClassLoader().getResource(name);
         System.out.println("URL: " + url);
         URLConnection conn = url.openConnection();
         System.out.println("Content-Length: " + conn.getContentLength());
         System.out.println("Content-Type: " + conn.getContentType());
         InputStream in = conn.getInputStream();
         byte[] bytes = in.readAllBytes();
         System.out.println("bytes.length: " + bytes.length);
     }
}


Prints the following:


URL: classbytes:/Test.class
Content-Length: 1763
Content-Type: application/octet-stream
bytes.length: 1763


Would that be enough for bytecode instrumentation tools?

Regards, Peter



More information about the core-libs-dev mailing list