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