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

Reply via email to