On 8/27/18 10:51 AM, Peter Levart wrote:


On 08/27/2018 04:47 PM, David Lloyd wrote:
On Mon, Aug 27, 2018 at 9:41 AM Alan Bateman <alan.bate...@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


Peter,

I like this form of solution; I like that we can fairly easily return a URL, from which the user can get a stream that is equivalent to using getResourceAsStream, without having to provide the "full-blown" solution.

-- Jon

Reply via email to