method references: type inference, toString()

Rémi Forax forax at univ-mlv.fr
Tue Feb 21 16:35:05 PST 2012


On 02/22/2012 01:16 AM, Vitaly Davidovich wrote:
>
> As they say, security by obscurity is not security :).  I can see 
> performance as an argument, but the security aspect seems invalid.
>

I agree, here security == part of the Java security model
like when you call Class.getDeclaredMethods
http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getDeclaredMethods%28%29

cheers,
Rémi

> Sent from my phone
>
> On Feb 21, 2012 6:33 PM, "Rémi Forax" <forax at univ-mlv.fr 
> <mailto:forax at univ-mlv.fr>> wrote:
>
>     On 02/21/2012 11:31 PM, Paul Holser wrote:
>     > Hi lambda-dev,
>     >
>     > Using JDK 8 Developer Preview with lambda support
>     >
>     (http://download.java.net/lambda/b25/windows-i586/lambda-8-b25-windows-i586-05_feb_2012.zip),
>     > Guava 11.0, Hamcrest 1.3.RC2, and JUnit 4.10 (sans Hamcrest
>     classes).
>     >
>     > org.hamcrest.Matcher is not a SAM type, whereas
>     > com.google.common.base.Predicate is.
>     >
>     > Compiling Main.java:
>     >
>     > ==== begin Main.java ====
>     > import com.google.common.base.Predicate;
>     > import org.hamcrest.Description;
>     > import org.hamcrest.TypeSafeMatcher;
>     > import org.junit.Test;
>     >
>     > import static org.hamcrest.MatcherAssert.assertThat;
>     >
>     > interface Foo {
>     >      boolean isBar();
>     > }
>     >
>     > abstract class PredicateMatcher<T>  extends TypeSafeMatcher<T>  {
>     >      protected final Predicate<? super T>  predicate;
>     >
>     >      private PredicateMatcher(Predicate<? super T>  predicate) {
>     >          this.predicate = predicate;
>     >      }
>     >
>     >      @Override public final boolean matchesSafely(T target) {
>     >          return predicate.apply(target);
>     >      }
>     >
>     >      public static<U>  PredicateMatcher<U>  matches(Predicate<?
>     super U>
>     > predicate) {
>     >          return new PredicateMatcher<U>(predicate) {
>     >              @Override public void describeTo(Description
>     description) {
>     >                  description.appendText("a value acceptable to
>     predicate ");
>     >                  description.appendValue(this.predicate);
>     >              }
>     >          };
>     >      }
>     > }
>     >
>     > class BarredUpFoo implements Foo {
>     >      @Override public boolean isBar() {
>     >          return true;
>     >      }
>     > }
>     >
>     > class BarredUpFooTest {
>     >      @Test public void bar() {
>     >         assertThat(new BarredUpFoo(),
>     PredicateMatcher.matches(Foo::isBar));
>     >      }
>     > }
>     >
>     > public class Main {
>     >      public static void main(String... args) {
>     >          Predicate<Foo>  bar = Foo::isBar;
>     >          System.out.println(bar);
>     >      }
>     > }
>     > ==== end Main.java ====
>     >
>     > yields:
>     >
>     > ==== begin console output ====
>     > Main.java:41: error: no suitable method found for matches(member
>     reference)
>     >         assertThat(new BarredUpFoo(),
>     PredicateMatcher.matches(Foo::isBar));
>     >                                                       ^
>     >      method PredicateMatcher.<U>matches(Predicate<? super U>) is
>     not applicable
>     >        (cyclic inference - cannot infer target type for given
>     lambda/method refer
>     > ence expression)
>     >      method TypeSafeMatcher.matches(Object) is not applicable
>     >        (actual argument member reference cannot be converted to
>     Object by method
>     > invocation conversion
>     >          (the target type of a lambda conversion must be an
>     interface))
>     >    where U is a type-variable:
>     >      U extends Object declared in method<U>matches(Predicate<?
>     super U>)
>     > 1 error
>     > ==== end console output ====
>     >
>     > Couple of questions:
>     >
>     > 1) Should the usage of Foo::isBar as the predicate fed to
>     > PredicateMatcher.matches() compile successfully? I'm hoping not to
>     > have to perform the SAM conversion by hand:
>     >
>     >      Predicate<Foo>  bar = Foo::isBar;
>     >      assertThat(new BarredUpFoo(), PredicateMatcher.matches(bar);
>     >
>     > In Main.main(), I perform that SAM conversion by hand, as you
>     can see
>     > -- otherwise, it won't know to choose
>     PrintStream.println(Object), it
>     > says "(actual argument member reference cannot be converted to
>     Object
>     > by method invocation conversion)".
>
>     I only answer easy question, I let this one to Maurizio :)
>
>     >
>     > 2) Wondering if it wouldn't be too much trouble to have method
>     > references respond to toString() with something like "Foo::isBar" or
>     > "method isBar on class Foo", instead of, e.g. "Main$1 at a30a4e". It'd
>     > make the output of PredicateMatcher.matches() really slick.
>
>     There are two major problems.
>     First security, if toString() exposes declaring class and method name
>     you may show to much information for an attacker. Don't forget that
>     the class may be non public and the method private.
>     Second, performance, we want a VM to be able to implement the SAM
>     conversion as a kind of proxy around a function pointer, i.e something
>     that may not carry around the fat Object data structure.
>
>     One possible solution.
>     Because we also want lambda/method reference to be Serializable
>     we are discussing an opt-in mechanism that will allow lambdas to
>     be Serializable by having a stable name (thus a meaningful toString).
>     But this kind of lambda may be less thin (and perhaps less efficient).
>
>     >
>     > Thanks for the help, and the great work thus far!
>     >
>     > Cheers,
>     > Paul Holser
>     >
>
>     cheers,
>     Rémi
>
>
>
>



More information about the lambda-dev mailing list