Proposal: Fully Concurrent ClassLoading

Zhong Yu zhong.j.yu at gmail.com
Fri Dec 14 14:58:34 UTC 2012


On Wed, Dec 12, 2012 at 5:48 PM, David Holmes <david.holmes at oracle.com> wrote:
> On 13/12/2012 1:51 AM, Zhong Yu wrote:
>>
>> If a class loader is declared fully concurrent, yet
>> getClassLoadingLock() is invoked, what's the harm of returning a
>> dedicated lock anyway, exactly like what's done before?
>
>
> The whole point is to get rid of the lockMap and these lock objects.
>
> I could return a sentinel Object in all cases rather than null but that just
> seems to encourage continued use of something that shouldn't be used with a
> fully concurrent loader.
>
> Returning null versus throwing an exception is mostly a matter of style. I'd
> want to hear from anyone who invokes getClassLoadingLock() on any of the
> system classloaders to see which is preferable.

Since this change will break some applications, the failure should be
loud, with immediate and detailed information on what's going on, so
the poor developers can fix the problem quickly.

I had the pleasure of implementing classloaders before, and I think it
might be underestimated how many classloaders are actually out there.

Zhong


> Thanks for the comments.
>
> David
>
>
>> On Tue, Dec 11, 2012 at 7:40 PM, David Holmes<david.holmes at oracle.com>
>> wrote:
>>>
>>> On 11/12/2012 9:58 PM, Peter Levart wrote:
>>>>
>>>>
>>>> On 12/11/2012 12:27 PM, David Holmes wrote:
>>>>>
>>>>>
>>>>> Peter,
>>>>>
>>>>> You are convincing me that all superclasses must be fully concurrent
>>>>> too. Otherwise we are just trying to second-guess a whole bunch of
>>>>> what-ifs. :)
>>>>
>>>>
>>>>
>>>> If you think some more, yes. The superclass might not use
>>>> getClassLoadingLock() but rely on the fact that findClass() is allways
>>>> called under a guard of per-class-name lock, for example. It's a matter
>>>> of how far to go to prevent such miss-behaving fully-concurrent
>>>> subclasses. So far to also prevent fully-concurrent subclasses that
>>>> would otherwise be perfectly correct?
>>>>
>>>> Maybe not. Creating custom ClassLoaders is not an average programmer's
>>>> job. Those that do this things will of course study the implementations
>>>> of superclasses they extend and do the right thing. And it's reasonable
>>>> to expect that they more or less will only extend JDK's ClassLoaders -
>>>> but on the other hand if they only extend JDK's class loaders, they are
>>>> not prevented to be fully-concurrent either way. Hm...
>>>
>>>
>>>
>>> Again I think it is just too hard to try and second-guess how a
>>> parallel-loader might rely on the per-class locks (I actually don't see
>>> any
>>> reasonable use for them beyond flow-control), and then how a concurrent
>>> loader subclass might need to modify things.
>>>
>>> If we simply disallow this then we can relax that constraint in the
>>> future
>>> if valid use-cases turn up for that capability. Of course if someone has
>>> a
>>> valid use-case during this discussion phase then of course that will
>>> influence the decision.
>>>
>>> Thanks,
>>> David
>>>
>>>> Peter
>>>>
>>>>>
>>>>> Thanks,
>>>>> David
>>>>>
>>>>> On 11/12/2012 7:44 PM, Peter Levart wrote:
>>>>>>
>>>>>>
>>>>>> On 12/11/2012 10:29 AM, David Holmes wrote:
>>>>>>>
>>>>>>>
>>>>>>> On 11/12/2012 7:20 PM, Peter Levart wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>> On 12/11/2012 03:55 AM, David Holmes wrote:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Question on the source code: registerAsFullyConcurrent has
>>>>>>>>>> confusing
>>>>>>>>>> comment -
>>>>>>>>>> do the super classes all need to be parallel capable? Or do the
>>>>>>>>>> super
>>>>>>>>>> classes all need
>>>>>>>>>> to be FullyConcurrent? I assume the latter, so just fix the
>>>>>>>>>> comments.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Actually it is the former. There's no reason to require that all
>>>>>>>>> superclasses be fully-concurrent. Of course a given loaders degree
>>>>>>>>> of
>>>>>>>>> concurrency may be constrained by what it's supertype allows, but
>>>>>>>>> there's no reason to actually force all the supertypes to be
>>>>>>>>> fully-concurrent: it is enough that they are at least all parallel
>>>>>>>>> capable.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> Hi David,
>>>>>>>>
>>>>>>>> There is one caveat: if ClassLoader X declares that it is
>>>>>>>> fully-concurrent and it's superclass Y is only parallel-capable,
>>>>>>>> then X
>>>>>>>> will act as fully-concurrent (returning null from
>>>>>>>> getClassLoadingLock()). superclass Y might or might not be coded to
>>>>>>>> use
>>>>>>>> the getClassLoadingLock(). X therefore has to know how Y is coded.
>>>>>>>> To be
>>>>>>>> defensive, X could ask for Y's registration and declare itself as
>>>>>>>> only
>>>>>>>> parallel-capable if Y declares the same so that when Y is upgraded
>>>>>>>> to be
>>>>>>>> fully-concurrent, X would become fully-concurrent automatically. To
>>>>>>>> support situations where the same version of X would work in two
>>>>>>>> environments where in one Y is only parallel-capable and in the
>>>>>>>> other Y
>>>>>>>> is fully-concurrent, there could be a static API to retrieve the
>>>>>>>> registrations of superclasses.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> I don't quite follow this. What code in the superclass are you
>>>>>>> anticipating that the subclass will use which relies on the lock? Or
>>>>>>> is this just an abstract "what if" scenario?
>>>>>>
>>>>>>
>>>>>>
>>>>>> This is more or less "what if". There might be a subclass Y of say
>>>>>> java.lang.ClassLoader that overrides loadClass or findClass, declares
>>>>>> that it is parallel-capable and in the implementation of it's
>>>>>> loadClass
>>>>>> or findClass, uses getClassLoadingLock() to synchronize access to it's
>>>>>> internal state. Now there comes class X extends Y that declares that
>>>>>> it
>>>>>> is fully-concurrent. Of course this will not work, X has to declare
>>>>>> that
>>>>>> it is parallel-capable, because Y uses getClassLoadingLock().
>>>>>>
>>>>>> What I suggested in the next message is to not change the registration
>>>>>> API but rather provide getClassLoadingLock() that returns non-null
>>>>>> locks
>>>>>> when any of the superclasses declare that they are only
>>>>>> parallel-capable, not fully-concurrent.
>>>>>>
>>>>>> Regards, Peter
>>>>>>
>>>>>>>
>>>>>>> Thanks,
>>>>>>> David
>>>>>>> -----
>>>>>>>
>>>>>>>> Or, to have less impact on future deprecation of old
>>>>>>>> parallel-capable
>>>>>>>> registration API, the fully-concurrent registration API:
>>>>>>>>
>>>>>>>> protected static boolean registerAsFullyConcurrent()
>>>>>>>>
>>>>>>>> might take a boolean parameter:
>>>>>>>>
>>>>>>>> protected static boolean registerAsFullyConcurrent(boolean
>>>>>>>> downgradeToPrallelCapableIfAnySuperclassIsNotFullyConcurrent)
>>>>>>>>
>>>>>>>>
>>>>>>>> and provide no accessible API to find out what the registration
>>>>>>>> actually
>>>>>>>> did (register as parallel-capable or fully-concurrent - return true
>>>>>>>> in
>>>>>>>> any case).
>>>>>>>>
>>>>>>>> Since all JDK provided ClassLoaders will be made fully concurrent,
>>>>>>>> this
>>>>>>>> might only be relevant if there is vendor A that currently provides
>>>>>>>> only
>>>>>>>> parallel-capable ClassLoader implementation and there is vendor B
>>>>>>>> that
>>>>>>>> subclasses A's loader and wants to upgrade and be backward
>>>>>>>> compatible at
>>>>>>>> the same time.
>>>>>>>>
>>>>>>>> Does this complicate things to much for no real benefit?
>>>>>>>>
>>>>>>>> Regards, Peter
>>>>>>>>
>>>>>>
>>>>
>>>
>



More information about the core-libs-dev mailing list