ClassLoader.getResources vs Module.getResourceAsStream
Stephen Colebourne
scolebourne at joda.org
Mon Jul 16 10:06:43 UTC 2018
In my experience (as I've written before), ClassLoader.getResources is
perhaps the biggest pain point I've experienced in trying to move
beyond Java 8. The method seems to have been very widely used, and IMO
was considered to be preferred over Class.getResourceXxx. And it is
very confusing to use once modules come into play.
There is no simple replacement for the ability to search for resources
across jar files. Module.getResourceXxx cannot be used as it only
returns one resource from the unamed module, when there could be many
(and the docs are no particularly clear on what they do). This is very
inconvenient. Returning a stream instead of a URL also typically
involves wider code change to adopt. In addition, many projects are
still on Java 8, so can't use java.lang.Module anyway.
ServiceLoader is completely the wrong solution for config files. Its
far too heavyweight.
My solution (which I think is pretty horrible) has been to move config
files to be under META-INF.
Old location:
org/joda/convert
New location:
META-INF/org/joda/convert
Its backwards incompatible to downstream users, but at least it works
with ClassLoader.getResources
Given there are no good solutions to normal coding problems, I can't
help feeling that Jigsaw didn't get resource access quite right.
Stephen
On 14 July 2018 at 16:31, Alan Bateman <Alan.Bateman at oracle.com> wrote:
> On 14/07/2018 14:00, Michał Zegan wrote:
>>
>> Hello.
>> When reading docs for jdk9 and jdk10 it seems that those methods work in
>> a bit different way when it goes to encapsulation:
>> Module.getResourceAsStream will retrieve the resource without a problem
>> if a package is opened to the caller module, probably including the fact
>> that it will find a resource when the calling module is the same as one
>> represented by the module object.
>> But, ClassLoader.getResources and other resource methods seem to require
>> unconditional package open.
>> Why? I don't quite understand that distinction.
>
> ClassLoaders, especially in a delegation chain, have no notion of "who" is
> trying to locate the resource. The ClassLoader.getResourceXXX methods are
> also not final. All told, the ClassLoader.getResourceXXX cannot reliably
> support qualified opens so this is why they are specified to only locate
> resources in modules when the package is open to all modules.
>
> The general guideline is to use Class or Module getResourceXXX when you want
> to locate a resource in your own module or another specific module. Use
> ClassLoader.getResourceXXX when you want to search the class path. If you
> follow that then it makes it a lot easier to migrate existing code to
> modules.
>
> -Alan
More information about the jigsaw-dev
mailing list