Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8019635

Use MethodType for LambdaMetafactory contract rather than MethodHandle

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P2 P2
    • 8
    • None
    • core-libs

      The metafactory parameter "MethodHandle samMethod" is confusing: what we're trying to encode is a MethodType + a name; but MethodHandles also carry with them stuff we don't care about (and must not, by contract): a class, an invocation mode, and implicit method resolution.

      (Diversion: does the class in the MethodHandle tell the MF what the generated class's superinterface should be? no, that comes from the invokedType ("()->SuperInterface").)

      When there are multiple methods to override, this can be confusing -- it suggests that the samMethod gets different treatment than the other methods (which are just MethodTypes), while in reality they are equal peers.

      But, more importantly, the fact that resolution happens raises the possibility of resolution errors. For example, the package-access limitation I find myself running into a lot lately:

      package p1; interface I { void m(); }
      package p1; public interface J extends I {}
      package p2; ... p1.J j = () -> {};

      This causes an IllegalAccessError, because javac mentions I in the MethodHandle pointing to I.m. There is no error in an anonymous class, because the class doesn't mention I.

      We could tweak the compiler to point to J.m instead, but that raises other problems: what happens if J.m is ambiguous?

      package p1; interface I { void m(); }
      package p1; interface K { default void m() {} }
      package p1; public interface J extends I,K {}

      (This would be a compile-time error, but you can get there with separate compilation...)

      Generally, it doesn't seem right that we are asking the VM to do some computation that i) is irrelevant, and ii) can cause errors. It's a neat trick to wrap up the method name in this way, but seems to have more baggage than was intended. So perhaps we should bite the bullet and just pass the method name as a String instead?

      (I've thought about using "invokedName", which is already there and "wasted" with "lambda$", although I get that, morally, the name of the method is "makeMeAFunction", not "apply" or whatever. I don't know what the invokedynamic conventions are for using/abusing that name.)

            rfield Robert Field (Inactive)
            dlsmith Dan Smith
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: