Proposal: #ResourceEncapsulation and #ClassFilesAsResources

Tim Ellison Tim_Ellison at uk.ibm.com
Wed Jun 29 10:15:38 UTC 2016


mark.reinhold at oracle.com (Mark Reinhold) wrote on 28/06/2016 22:20:15:
> Issue summaries
> ---------------
> 
>   #ClassFilesAsResources --- If a type is visible and was loaded from a
>   class file then it should be possible to read that file by invoking 
the
>   `getResourceAsStream` method of the type's class loader, as it is in
>   earlier releases. [1]
> 
>   #ResourceEncapsulation --- The `Module::getResourceAsStream` method 
can
>   be used to read the resources of any named module, without 
restriction,
>   which violates the resource-encapsulation requirement [2].  This 
method
>   should be restricted somehow so that only "suitably-privileged" code
>   (for some definition of that term) can access resources in a named
>   module other than its own.  An alternative is to drop this
>   requirement. [3]
> 
> Proposal
> --------
> 
> Drop the agreed resource-encapsulation requirement, which reads:
> 
>   Resource encapsulation --- The run-time system must ensure that the
>   static resource files within a module are directly accessible only by
>   code within that module.  The existing resource-access APIs should
>   continue to work as they do today when used to access a module's own
>   resource files. [2]
> 
> Make the following changes to the various `getResource*` methods:
> 
>   - The `ClassLoader::getResource*` methods will first delegate to the
>     loader's parent, if any, and will then search for resources in the
>     named modules defined to the loader, and will then search in the
>     loader's unnamed module, typically defined by a class path.  In the
>     case of the `getResources` method the order of the resources in the
>     returned enumeration will be unspecified, except that the values of
>     `cl.getResources(name).nextElement()` and `cl.getResource(name)`
>     will be equal.
> 
>   - The `Class::getResource*` methods will only search for resources in
>     the module that defines the class.  In the case of a class in an
>     unnamed module this will typically result in searching the class
>     path of the corresponding class loader.
> 
> The `java.lang.reflect.Module::getResourceAsStream` method will remain,
> so that it's possible to look up a resource in a module without having a
> reference to a class defined in that module.  It will always be the case
> that, for a given a class `c`, `c.getResourceAsStream(name)` will be
> equivalent to `c.getModule().getResourceAsStream(name)`.
> 
> 
> Rationale
> ---------
> 
> The encapsulation of resources was intended to be part of the overall
> encapsulation story, on the view that a module's resources are just
> internal implementation details that need not, and should not, be
> available to code in other modules.  Allowing external code to depend
> upon a module's internal resources is just as problematic as allowing
> such code to depend upon internal APIs.
> 
> The reality of existing code today, however, is rather different, with
> two common use cases:
> 
>   - Resources are often used intentionally to convey information to
>     external code, e.g., as a way to publish configuration files such as
>     `persistence.xml`.  This sort of thing should, ideally, be done via
>     services [4][5], but that is not the current practice and it will
>     take years to migrate to it.
> 
>   - Various popular tools and byte-code manipulation frameworks expect 
to
>     be able to load class files as resources, i.e., to access the class
>     file that defines a class `p.q.C` by invoking `getResource("p.q.C")`
>     on that class's loader.
> 
> With the API as it stands today these use cases can still be supported,
> but the code that looks up the resource must be converted to use the
> `Module::getResourceAsStream` method.  This is a barrier to migration,
> since it means that fewer existing frameworks will work out-of-the-box
> as automatic modules.
> 
> We should not drop agreed requirements lightly, but now that we have
> some practical experience with an implementation of this one I think
> it's clear that the pain outweighs the gain.
> 
> 
> [1] 
http://openjdk.java.net/projects/jigsaw/spec/issues/#ClassFilesAsResources
> [2] 
http://openjdk.java.net/projects/jigsaw/spec/reqs/#resource-encapsulation
> [3] 
http://openjdk.java.net/projects/jigsaw/spec/issues/#ResourceEncapsulation
> [4] http://mail.openjdk.java.net/pipermail/jpms-spec-experts/2015-
> October/000163.html
> [5] http://mail.openjdk.java.net/pipermail/jpms-spec-experts/2015-
> December/000207.html
> [6] http://mail.openjdk.java.net/pipermail/jigsaw-dev/2015-
> September/004486.html
> [7] http://mail.openjdk.java.net/pipermail/jigsaw-dev/2015-November/
> 005240.html
 
The proposal to drop this requirement leaves no way for a module to 
encapsulate
its resources.  Have you considered an alternative that preserves the 
compatibility
of existing APIs which I agree is desirable to support existing 
applications,
but introduces a module-level resource API that allows those modules that 
want
to hide their implementation details?

Regards,
Tim


Unless stated otherwise above:
IBM United Kingdom Limited - Registered in England and Wales with number 
741598. 
Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire PO6 3AU


More information about the jpms-spec-observers mailing list