8019622: (sl) ServiceLoadet.next incorrect when creation and usages are in different contexts

Remi Forax forax at univ-mlv.fr
Wed Jul 3 17:56:19 UTC 2013

On 07/03/2013 07:01 PM, Alan Bateman wrote:
> On 03/07/2013 17:24, Remi Forax wrote:
>> Hi Alan,
>> you can use a method reference instead a lambda here,
>> so
>>   PrivilegedAction<Boolean> action = () -> hasNextService();
>> return AccessController.doPrivileged(action, acc);
>> can be written
>>   return AccessController.doPrivileged(this::hasNextService, acc);
>> (me crossing my fingers in hope that the compiler will not be 
>> confused by the overloads).
> There is a problem using method references here that need to be 
> tracked down. In TypeConvertingMethodAdapter where it handles boxing 
> then String.format is used but that triggers the loading of formatter 
> providers and recursive initialization that blows the stack and 
> manifests as a BootstrapMethodError. I need to ask Robert about this 
> or bring it up on lambda-dev as I'm not sure why this doesn't happen 
> with a lambda. If we have a bootstrapping issue then it may be that 
> ServiceLoader will need to use an inner class here.

Interesting !
it's related to the way the compiler desugar lambda vs method reference.

I've not taken a look to the generated code but I think I know why the 
behaviour is different.
If the code uses a lambda:
   PrivilegedAction<Boolean> action = () -> hasNextService();
the compiler will create a private method lambda$n and will infer it's 
parameter type and return type,
here the infered return type is Boolean and not boolean, so the boxing 
of the result of hasNextService()
is done inside the method lambda$n.

If the code uses a method reference:
PrivilegedAction<Boolean> action = this::hasNextService;
No method lambda$n is generated, the compiler uses the method 
hasNextService, so the boxing
need to be done in the generated proxy at runtime.

So the way to fix this issue is to not use String.format in boxingDescriptor
(It's the only method in TypeConvertingMethodAdapter  that uses format)

private static String boxingDescriptor(Wrapper w) {
   return '(' + w.basicTypeChar() + ")L" + wrapperName(w) + ';'

> AccessController.doPrivileged does have overloads that javac reports 
> as ambiguous.

Yes, after sending this mail, I recall that the EG decide to not 
disambiguate overloads based
on the fact that the lambda/method reference declare to throw an 
exception or not.

> As it happens someone made a good suggestion recently on security-dev 
> that the new limited doPrivlieged methods take this into account.

or to write two lines instead of one:
PrivilegedAction<Boolean> action = this::hasNextService;
   return AccessController.doPrivileged(action, acc);

> -Alan.


More information about the core-libs-dev mailing list