java.dyn
Class JavaMethodHandle

java.lang.Object
  extended by sun.dyn.MethodHandleImpl
      extended by java.dyn.MethodHandle
          extended by sun.dyn.BoundMethodHandle
              extended by java.dyn.JavaMethodHandle

public abstract class JavaMethodHandle
extends sun.dyn.BoundMethodHandle

Disabled: no SafeJ information.

A Java method handle extends the basic method handle type with additional programmer defined methods and fields. Its behavior as a method handle is determined at instance creation time, by providing the new instance with an "entry point" method handle to handle calls. This entry point must accept a leading argument whose type is the Java method handle itself or a supertype, and the entry point is always called with the Java method handle itself as the first argument. This is similar to ordinary virtual methods, which also accept the receiver object this as an implicit leading argument. The MethodType of the Java method handle is the same as that of the entry point method handle, with the leading parameter type omitted.

Here is an example of usage, creating a hybrid object/functional datum:

 class Greeter extends JavaMethodHandle {
     private String greeting = "hello";
     public void setGreeting(String s) { greeting = s; }
     public void run() { System.out.println(greeting+", "+greetee); }
     private final String greetee;
     Greeter(String greetee) {
         super(RUN); // alternatively, super("run")
         this.greetee = greetee;
     }
     // the entry point function is computed once:
     private static final MethodHandle RUN
         = MethodHandles.lookup().findVirtual(Greeter.class, "run",
               MethodType.make(void.class));
 }
 // class Main { public static void main(String... av) { ...
 Greeter greeter = new Greeter("world");
 greeter.run();  // prints "hello, world"
 // Statically typed method handle invocation (most direct):
 MethodHandle mh = greeter;
 mh.<void>invoke();  // also prints "hello, world"
 // Dynamically typed method handle invocation:
 MethodHandles.invoke(greeter);  // also prints "hello, world"
 greeter.setGreeting("howdy");
 mh.invoke();  // prints "howdy, world" (object-like mutable behavior)
 

In the example of Greeter, the method run provides the entry point. The entry point need not be a constant value; it may be independently computed in each call to the constructor. The entry point does not even need to be a method on the Greeter class, though that is the typical case.

The entry point may also be provided symbolically, in which case the the JavaMethodHandle constructor performs the lookup of the entry point. This makes it possible to use JavaMethodHandle to create an anonymous inner class:

 // We can also do this with symbolic names and/or inner classes:
 MethodHandles.invoke(new JavaMethodHandle("yow") {
     void yow() { System.out.println("yow, world"); }
 });
 

Here is similar lower-level code which works in terms of a bound method handle.

     class Greeter {
         public void run() { System.out.println("hello, "+greetee); }
         private final String greetee;
         Greeter(String greetee) { this.greetee = greetee; }
         // the entry point function is computed once:
         private static final MethodHandle RUN
             = MethodHandles.findVirtual(Greeter.class, "run",
                   MethodType.make(void.class));
     }
     // class Main { public static void main(String... av) { ...
     Greeter greeter = new Greeter("world");
     greeter.run();  // prints "hello, world"
     MethodHandle mh = MethodHanndles.insertArgument(Greeter.RUN, 0, greeter);
     mh.invoke();  // also prints "hello, world"
 
Note that the method handle must be separately created as a view on the base object. This increases footprint, complexity, and dynamic indirections.

Here is a pure functional value expressed most concisely as an anonymous inner class:

     // class Main { public static void main(String... av) { ...
     final String greetee = "world";
     MethodHandle greeter = new JavaMethodHandle("run") {
         private void run() { System.out.println("hello, "+greetee); }
     }
     greeter.invoke();  // prints "hello, world"
 

Here is an abstract parameterized lvalue, efficiently expressed as a subtype of MethodHandle, and instantiated as an anonymous class. The data structure is a handle to 1-D array, with a specialized index type (long). It is created by inner class, and uses signature-polymorphic APIs throughout.

     abstract class AssignableMethodHandle extends JavaMethodHandle {
       private final MethodHandle setter;
       public MethodHandle setter() { return setter; }
       public AssignableMethodHandle(String get, String set) {
         super(get);
         MethodType getType = this.type();
         MethodType setType = getType.insertParameterType(getType.parameterCount(), getType.returnType()).changeReturnType(void.class);
         this.setter = MethodHandles.publicLookup().bind(this, set, setType);
       }
     }
     // class Main { public static void main(String... av) { ...
     final Number[] stuff = { 123, 456 };
     AssignableMethodHandle stuffPtr = new AssignableMethodHandle("get", "set") {
         public Number get(long i)           { return stuff[(int)i]; }
         public void   set(long i, Object x) {        stuff[(int)i] = x; }
     }
     int x = (Integer) stuffPtr.<Number>invoke(1L);  // 456
     stuffPtr.setter().<void>invoke(0L, (Number) 789);  // replaces 123 with 789
 

See Also:
MethodHandle

Nested Class Summary
 
Nested classes/interfaces inherited from class sun.dyn.MethodHandleImpl
sun.dyn.MethodHandleImpl.MethodHandleFriend
 
Field Summary
 
Fields inherited from class sun.dyn.MethodHandleImpl
vmtarget
 
Constructor Summary
protected JavaMethodHandle(MethodHandle entryPoint)
          When creating a JavaMethodHandle, the actual method handle invocation behavior will be delegated to the specified entryPoint.
protected JavaMethodHandle(String entryPointName)
          Create a method handle whose entry point is a non-static method visible in the exact (most specific) class of the newly constructed object.
protected JavaMethodHandle(String entryPointName, MethodType type)
          Create a method handle whose entry point is a non-static method visible in the exact (most specific) class of the newly constructed object.
 
Method Summary
 
Methods inherited from class sun.dyn.BoundMethodHandle
toString
 
Methods inherited from class java.dyn.MethodHandle
asCollector, asSpreader, asType, bindTo, invokeExact, invokeGeneric, invokeGeneric, invokeGeneric, invokeGeneric, invokeGeneric, invokeGeneric, invokeGeneric, invokeGeneric, invokeGeneric, invokeGeneric, invokeGeneric, invokeVarargs, invokeVarargs, type
 
Methods inherited from class sun.dyn.MethodHandleImpl
accessArrayElement, accessField, addTypeString, bindArgument, bindReceiver, checkSpreadArgument, collectArguments, convertArguments, dropArguments, filterArgument, findMethod, foldArguments, getLookup, getNameString, init, initLookup, initStatics, makeGuardWithCatch, makeGuardWithTest, raiseException, setMethodHandleFriend, spreadArguments, throwException
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Constructor Detail

JavaMethodHandle

protected JavaMethodHandle(MethodHandle entryPoint)
Class is disabled.

When creating a JavaMethodHandle, the actual method handle invocation behavior will be delegated to the specified entryPoint. This may be any method handle which can take the newly constructed object as a leading parameter.

The method handle type of this (i.e, the fully constructed object) will be entryPoint, minus the leading argument. The leading argument will be bound to this on every method handle invocation.

Parameters:
entryPoint - the method handle to handle calls

JavaMethodHandle

protected JavaMethodHandle(String entryPointName,
                           MethodType type)
Class is disabled.

Create a method handle whose entry point is a non-static method visible in the exact (most specific) class of the newly constructed object.

The method is specified by name and type, as if via this expression: MethodHandles.lookup().findVirtual(this.getClass(), name, type). The class defining the method might be an anonymous inner class.

The method handle type of this (i.e, the fully constructed object) will be the given method handle type. A call to this will invoke the selected method. The receiver argument will be bound to this on every method handle invocation.

Rationale: Although this constructor may seem to be a mere luxury, it is not subsumed by the more general constructor which takes any MethodHandle as the entry point argument. In order to convert an entry point name to a method handle, the self-class of the object is required (in order to do the lookup). The self-class, in turn, is generally not available at the time of the constructor invocation, due to the rules of Java and the JVM verifier. One cannot call this.getClass(), because the value of this is inaccessible at the point of the constructor call. (Changing this would require change to the Java language, verifiers, and compilers.) In particular, this constructor allows JavaMethodHandles to be created in combination with the anonymous inner class syntax.

Parameters:
entryPointName - the name of the entry point method
type - (optional) the desired type of the method handle

JavaMethodHandle

protected JavaMethodHandle(String entryPointName)
Class is disabled.

Create a method handle whose entry point is a non-static method visible in the exact (most specific) class of the newly constructed object.

The method is specified only by name. There must be exactly one method of that name visible in the object class, either inherited or locally declared. (That is, the method must not be overloaded.)

The method handle type of this (i.e, the fully constructed object) will be the same as the type of the selected non-static method. The receiver argument will be bound to this on every method handle invocation.

ISSUE: This signature wildcarding feature does not correspond to any MethodHandles.Lookup API element. Can we eliminate it? Alternatively, it is useful for naming non-overloaded methods. Shall we make type arguments optional in the Lookup methods, throwing an error in cases of ambiguity?

For this method's rationale, see the documentation for JavaMethodHandle(String,MethodType).

Parameters:
entryPointName - the name of the entry point method