RFR 8064924: Update java.net.URL to work with modules

Peter Levart peter.levart at gmail.com
Sun Feb 1 09:25:00 UTC 2015


Hi Bernd,

On 02/01/2015 01:14 AM, Bernd wrote:
>
> Hello,
>
> What about simply rejecting overlapping programmatic registrations,
>

This can't work by registering URLStreamHandlerFactory objects as they 
don't announce their supported protocols. Perhaps registering 
URLStreamHandler objects directly would be an option as in:

public static void setURLStreamHandler(String protocol, URLStreamHandler 
urlStreamHandler) throws IllegalStateException

But this per-protocol registration (or any programmatic registration 
that overrides previous defaults) has a drawback that you can end up 
with URL instances for the same protocol but different URLStreamHandler, 
depending on when they are constructed, so it can happen that 
URL("http://www.google.com/") is not equal to 
URL("http://www.google.com/"). Sometimes you actually want that (see 
Alan's note about loading a "jar" URLStreamHandler deployed in a jar 
file), but otherwise it gives you a very fragile system that depends on 
initialization order. Programmatic registration should be reserved for 
the master of the universe (to be performed before the universe is 
born). Otherwise, special protocol handlers are better registered 
declaratively.

> and for the service loader using the natural order (class loader 
> search order). I guess most extensions register new schemes only, as 
> it was not easy before in such a central shared system component. an 
> ordering api might not really help. Its might be better to allow 
> specific versions like a factory or even something thread local? 
> (Similar to jndi enc)
>

If you want to have multiple universes in the same VM where each has 
it's own view of per-protocol URLStreamHandlers, then you must ensure 
that URL instances constructed in each universe, don't come in contact 
with each other or you will be subjected to similar issues as when two 
Class objects with same class name are not equal to each other, because 
each is loaded by different ClassLoader.

Regards, Peter

> Bernd
>
> Am 01.02.2015 00:48 schrieb "Peter Levart" <peter.levart at gmail.com 
> <mailto:peter.levart at gmail.com>>:
>
>     Hi Alan,
>
>     On 01/31/2015 10:33 PM, Alan Bateman wrote:
>>     On 31/01/2015 19:42, Peter Levart wrote:
>>>     Hi Chris,
>>>
>>>     I looked at your solution to make URLStreamHandlerFactory
>>>     interface a service provider using ServiceLoader API and in
>>>     addition adding new URL static method to programmaticaly
>>>     register URLStreamHandlerFactories. There are a couple of issues
>>>     with your approach I'd like to discuss.
>>>
>>>     The programmatic approach using static URL method does give you
>>>     some means of order in which registered
>>>     URLStreamHandlerFactories are tried to create URLStreamHandler
>>>     for particular protocol - the registration order. It means that
>>>     this method should only be called by one "party" in the VM or
>>>     else it is hard to control the order of registration.
>>>
>>>     ServiceLoader is a declarative approach, but does not give you
>>>     order by default. Also, your ServiceLoader approach gives a way
>>>     for URLStreamHandlerFactories to register in the system without
>>>     security checks. If a particular
>>>     META-INF/services/java.net.URLStreamHandlerFactory is found,
>>>     it's content is used to load a class and instantiate a factory
>>>     which is used in URL constructors then. Previously, one had to
>>>     have a "setFactory" permission to set the
>>>     URLStreamHandlerFactory or appropriate PropertyPermission for
>>>     seting the package prefix property. This can be fixed.
>>>
>>>     :
>>>
>>>     Anyway, I think there is an alternative to programmatic
>>>     registration approach of URLStreamHandlerFactories. Using just
>>>     ServiceLoader and a new default method on
>>>     URLStreamHandlerFactory interface to provide order. Here's what
>>>     I'm thinking about:
>>>
>>>     http://cr.openjdk.java.net/~plevart/jdk9-dev/URLStreamHandlerFactory/webrev.01/
>>>     <http://cr.openjdk.java.net/%7Eplevart/jdk9-dev/URLStreamHandlerFactory/webrev.01/>
>>
>>     I don't think we should we expose ordering values in
>>     URLStreamHandlerFactory, it looks a bit odd and not clear how an
>>     implementation can choose a useful value. There is a general
>>     issue that ServiceLoader doesn't currently support a means to
>>     order service providers but I think we can re-examine that when
>>     we move to modules and and linking. That is, have a consistent
>>     way to configure ordering that we can use everywhere that
>>     ServiceLoader is used rather than doing one-off solutions.
>
>     I agree. Putting the order on the SPI API is not the right
>     solution. The order should be configured in one place. But there
>     needs to be some kind of handle each service exposes for order
>     configuration to reference. So one idea how to extend the
>     ServiceLoader mechanism is this:
>
>     create a special class-scope runtime annotation...
>
>     public @interface ServiceProvider {
>             String name();
>     }
>
>     ...with which service implementation classes can optionally be
>     annotated. This could enable ServiceLoader API extension like:
>
>         public static <S> ServiceLoader<S> load(Class<S> service,
>     String serviceProviderName)
>
>     that would return an Iterable over implementations that are
>     annotated with a particular @ServiceProvider(name = ...)
>     annotation (similar to security Providers but simpler).
>
>     In addition one could specify a system property with the key being
>     prefixed by service interface FQ class name, like:
>
>     java.net.URLStreamHandlerFactory.serviceLoaderOrder=providerName1,providerName2,providerName3,...
>
>
>
>>
>>     The other thing is that it's not clear how this would work for a
>>     factory for the jar protocol that is itself deployed in a JAR
>>     file on the class path. This is important for containers that
>>     want to do their own caching and they want their jar protocol
>>     handler configured system-wide before starting any applications.
>>     It's also part of the motive for the addURLStreamHandlerFactory
>>     in the original proposal.
>
>     I see. But isn't URL.setURLStreamHandlerFactory() enough for that
>     purpose? It can only be set once, but there can only be *one*
>     container that wants it's jar protocol handler configured system-wide.
>
>     Regards, Peter
>
>>
>>     I think you have good point with the setFactory permission, that
>>     does need to be looked at.
>>
>>     -Alan.
>




More information about the core-libs-dev mailing list