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.
Rémi