JEP 330 and MemoryClassLoader.getResourceAsStream

Peter Levart peter.levart at gmail.com
Tue Sep 4 12:17:12 UTC 2018


Hello,

On 08/27/2018 04:11 AM, seth lytle wrote:
> to add to what Jon said, recompiling doesn't necessarily provide the 
> correct info as it may have been manipulated by another agent or 
> classloader (there is a similar weakness in my current workaround)
>
> getResourceAsStream (getRAS) is:
> - robust: you know it's the same bytecode your parent CL used
> - flexible: you can run woven and unwoven code concurrently
> - chainable: downstream CLs will see your modifications
>
>
> i haven't been able to think of anything that getResource adds, though 
> some people may use that instead
>
> on the core-libs-dev list 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.
>
>
> @jon - would you like to reply to that or should i ?
>
> my feeling is that we're better off without getResource (getR)
> - the javadocs appear to allow differences between getR and getRAS
> - getR adds complexity, startup cost and increases footprint

Not that much. Most code can be in separate classes which are loaded 
only if .getResourceXXX is actually used.

> - we're not aware of a consumer of the getR api

Which does not mean there is none.

> - the only resource is bytecode, and that's naturally accessed as a stream
> - many things are changing with java 11 so any bytecode-modifying 
> library is likely to need to make source code changes anyway
>
> the only problem i see with not implementing getR is that there's no 
> way to convey to a hypothetical consumer of the API that the bytecode 
> that they're looking for is available via getRAS

The correct way, I think, is to implement findResource() and 
findResources(). getResource(), getResources() and getResourceAsStream() 
are just front-end methods to be called by users. They implement 
ClassLoader delegation model and call findResource(s) at appropriate 
time. Making getResourceAsStream() available, but getResource() always 
return null (or even throw exception?) would be a precedent, I think.

Here's a prototype that works and is not that complicated:

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

Someone might say that the URL protocol in this implementation does not 
allow parsing such URL(s) from String(s). That's true, but if one wanted 
to do that, one would have to identify (in the URL) the target 
MemoryClassLoader instance. There may be more than one MemoryClassLoader 
instance in the JVM. Comparing it to other protocols: in 
http://host:port/path/resource, the host:port part of the URL uniquely 
identifies the http server, where the resources are located; in 
file:///path/resource, the protocol refers to the single local file 
system on the host machine where the JVM is running, etc. How would one 
identify multiple instances of MemoryClassLoader such that their unique 
"names" would be known in advance? No way.

I think that the presented prototype strikes the balance where the full 
resource resolving API of ClassLoader is implemented, while the URL 
protocol is not supported in a way that would allow parsing such URL(s) 
from String(s).

If this is acceptable compromise, I suggest moving in this direction.

Regards, Peter



More information about the compiler-dev mailing list