1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/share/classes/java/dyn/BootstrapMethod.java Wed Nov 10 20:40:19 2010 -0800
1.3 @@ -0,0 +1,82 @@
1.4 +/*
1.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1.7 + *
1.8 + * This code is free software; you can redistribute it and/or modify it
1.9 + * under the terms of the GNU General Public License version 2 only, as
1.10 + * published by the Free Software Foundation. Oracle designates this
1.11 + * particular file as subject to the "Classpath" exception as provided
1.12 + * by Oracle in the LICENSE file that accompanied this code.
1.13 + *
1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1.17 + * version 2 for more details (a copy is included in the LICENSE file that
1.18 + * accompanied this code).
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License version
1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1.23 + *
1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1.25 + * or visit www.oracle.com if you need additional information or have any
1.26 + * questions.
1.27 + */
1.28 +
1.29 +package java.dyn;
1.30 +
1.31 +import java.lang.annotation.*;
1.32 +
1.33 +/**
1.34 + * Annotation on InvokeDynamic method calls which requests the JVM to use a specific
1.35 + * <a href="package-summary.html#bsm">bootstrap method</a>
1.36 + * to link the call. This annotation is not retained as such in the class file,
1.37 + * but is transformed into a constant-pool entry for the invokedynamic instruction which
1.38 + * specifies the desired bootstrap method.
1.39 + * <p>
1.40 + * If only the <code>value</code> is given, it must name a subclass of {@link CallSite}
1.41 + * with a constructor which accepts a class, string, and method type.
1.42 + * If the <code>value</code> and <code>name</code> are both given, there must be
1.43 + * a static method in the given class of the given name which accepts a class, string,
1.44 + * and method type, and returns a reference coercible to {@link CallSite}.
1.45 + * <p>
1.46 + * This annotation can be placed either on the return type of a single {@link InvokeDynamic}
1.47 + * call (see examples) or else it can be placed on an enclosing class or method, where it
1.48 + * determines a default bootstrap method for any {@link InvokeDynamic} calls which are not
1.49 + * specifically annotated with a bootstrap method.
1.50 + * Every {@link InvokeDynamic} call must be given a bootstrap method.
1.51 + * <p>
1.52 + * Examples:
1.53 +<blockquote><pre>
1.54 +@BootstrapMethod(value=MyLanguageRuntime.class, name="bootstrapDynamic")
1.55 +String x = (String) InvokeDynamic.greet();
1.56 +//BSM => MyLanguageRuntime.bootstrapDynamic(Here.class, "greet", methodType(String.class))
1.57 +@BootstrapMethod(MyCallSite.class)
1.58 +void example() throws Throwable {
1.59 + InvokeDynamic.greet();
1.60 + //BSM => new MyCallSite(Here.class, "greet", methodType(void.class))
1.61 +}
1.62 +</pre></blockquote>
1.63 + * <p>
1.64 + */
1.65 +@Target({ElementType.TYPE_USE,
1.66 + // For defaulting every indy site within a class or method; cf. @SuppressWarnings:
1.67 + ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR
1.68 + })
1.69 +@Retention(RetentionPolicy.SOURCE)
1.70 +public @interface BootstrapMethod {
1.71 + /** The class containing the bootstrap method. */
1.72 + Class<?> value();
1.73 +
1.74 + /** The name of the bootstrap method.
1.75 + * If this is the empty string, an instance of the bootstrap class is created,
1.76 + * and a constructor is invoked.
1.77 + * Otherwise, there must be a static method of the required name.
1.78 + */
1.79 + String name() default ""; // empty string denotes a constructor with 'new'
1.80 +
1.81 + /** The argument types of the bootstrap method, as passed out by the JVM.
1.82 + * There is usually no reason to override the default.
1.83 + */
1.84 + Class<?>[] arguments() default {Class.class, String.class, MethodType.class};
1.85 +}
2.1 --- a/src/share/classes/java/dyn/CallSite.java Tue Nov 09 22:53:18 2010 -0800
2.2 +++ b/src/share/classes/java/dyn/CallSite.java Wed Nov 10 20:40:19 2010 -0800
2.3 @@ -25,56 +25,26 @@
2.4
2.5 package java.dyn;
2.6
2.7 -import sun.dyn.Access;
2.8 -import sun.dyn.MemberName;
2.9 -import sun.dyn.CallSiteImpl;
2.10 +import sun.dyn.*;
2.11 +import java.util.Collection;
2.12
2.13 /**
2.14 - * A {@code CallSite} reifies an {@code invokedynamic} instruction from bytecode,
2.15 - * and controls its linkage.
2.16 - * Every linked {@code CallSite} object corresponds to a distinct instance
2.17 - * of the {@code invokedynamic} instruction, and vice versa.
2.18 + * A {@code CallSite} is a holder for a variable {@link MethodHandle},
2.19 + * which is called its {@code target}.
2.20 + * Every call to a {@code CallSite} is delegated to the site's current target.
2.21 * <p>
2.22 - * Every linked {@code CallSite} object has one state variable,
2.23 - * a {@link MethodHandle} reference called the {@code target}.
2.24 - * This reference is never null. Though it can change its value
2.25 - * successive values must always have exactly the {@link MethodType method type}
2.26 - * called for by the bytecodes of the associated {@code invokedynamic} instruction
2.27 + * A call site is initially created in an <em>unlinked</em> state,
2.28 + * which is distinguished by a null target variable.
2.29 + * Before the call site may be invoked (and before certain other
2.30 + * operations are attempted), the call site must be linked to
2.31 + * a non-null target.
2.32 * <p>
2.33 - * It is the responsibility of each class's
2.34 - * {@link Linkage#registerBootstrapMethod(Class, MethodHandle) bootstrap method}
2.35 - * to produce call sites which have been pre-linked to an initial target method.
2.36 - * The required {@link MethodType type} for the target method is a parameter
2.37 - * to each bootstrap method call.
2.38 - * <p>
2.39 - * The bootstrap method may elect to produce call sites of a
2.40 - * language-specific subclass of {@code CallSite}. In such a case,
2.41 - * the subclass may claim responsibility for initializing its target to
2.42 - * a non-null value, by overriding {@link #initialTarget}.
2.43 - * <p>
2.44 - * An {@code invokedynamic} instruction which has not yet been executed
2.45 - * is said to be <em>unlinked</em>. When an unlinked call site is executed,
2.46 - * the containing class's bootstrap method is called to manufacture a call site,
2.47 - * for the instruction. If the bootstrap method does not assign a non-null
2.48 - * value to the new call site's target variable, the method {@link #initialTarget}
2.49 - * is called to produce the new call site's first target method.
2.50 - * <p>
2.51 - * A freshly-created {@code CallSite} object is not yet in a linked state.
2.52 - * An unlinked {@code CallSite} object reports null for its {@code callerClass}.
2.53 - * When the JVM receives a {@code CallSite} object from a bootstrap method,
2.54 - * it first ensures that its target is non-null and of the correct type.
2.55 - * The JVM then links the {@code CallSite} object to the call site instruction,
2.56 - * enabling the {@code callerClass} to return the class in which the instruction occurs.
2.57 - * <p>
2.58 - * Next, the JVM links the instruction to the {@code CallSite}, at which point
2.59 - * any further execution of the {@code invokedynamic} instruction implicitly
2.60 - * invokes the current target of the {@code CallSite} object.
2.61 - * After this two-way linkage, both the instruction and the {@code CallSite}
2.62 - * object are said to be linked.
2.63 - * <p>
2.64 - * This state of linkage continues until the method containing the
2.65 - * dynamic call site is garbage collected, or the dynamic call site
2.66 - * is invalidated by an explicit request.
2.67 + * A call site may be <em>relinked</em> by changing its target.
2.68 + * The new target must be non-null and must have the same
2.69 + * {@linkplain MethodHandle#type() type}
2.70 + * as the previous target.
2.71 + * Thus, though a call site can be relinked to a series of
2.72 + * successive targets, it cannot change its type.
2.73 * <p>
2.74 * Linkage happens once in the lifetime of any given {@code CallSite} object.
2.75 * Because of call site invalidation, this linkage can be repeated for
2.76 @@ -87,6 +57,10 @@
2.77 * Here is a sample use of call sites and bootstrap methods which links every
2.78 * dynamic call site to print its arguments:
2.79 <blockquote><pre><!-- see indy-demo/src/PrintArgsDemo.java -->
2.80 +@BootstrapMethod(value=PrintArgsDemo.class, name="bootstrapDynamic")
2.81 +static void test() throws Throwable {
2.82 + InvokeDynamic.baz("baz arg", 2, 3.14);
2.83 +}
2.84 private static void printArgs(Object... args) {
2.85 System.out.println(java.util.Arrays.deepToString(args));
2.86 }
2.87 @@ -96,17 +70,16 @@
2.88 Class thisClass = lookup.lookupClass(); // (who am I?)
2.89 printArgs = lookup.findStatic(thisClass,
2.90 "printArgs", MethodType.methodType(void.class, Object[].class));
2.91 - Linkage.registerBootstrapMethod("bootstrapDynamic");
2.92 }
2.93 private static CallSite bootstrapDynamic(Class caller, String name, MethodType type) {
2.94 // ignore caller and name, but match the type:
2.95 return new CallSite(MethodHandles.collectArguments(printArgs, type));
2.96 }
2.97 </pre></blockquote>
2.98 - * @see Linkage#registerBootstrapMethod(java.lang.Class, java.dyn.MethodHandle)
2.99 * @author John Rose, JSR 292 EG
2.100 */
2.101 public class CallSite
2.102 + implements MethodHandleProvider
2.103 {
2.104 private static final Access IMPL_TOKEN = Access.getToken();
2.105
2.106 @@ -209,6 +182,7 @@
2.107 * {@code InvokeDynamicBootstrapError}, which in turn causes the
2.108 * linkage of the {@code invokedynamic} instruction to terminate
2.109 * abnormally.
2.110 + * @deprecated transitional form defined in EDR but removed in PFD
2.111 */
2.112 protected MethodHandle initialTarget(Class<?> callerClass, String name, MethodType type) {
2.113 throw new InvokeDynamicBootstrapError("target must be initialized before call site is linked: "+name+type);
2.114 @@ -278,16 +252,44 @@
2.115 */
2.116 @Override
2.117 public String toString() {
2.118 - StringBuilder buf = new StringBuilder("CallSite#");
2.119 - buf.append(hashCode());
2.120 - if (!isLinked())
2.121 - buf.append("[unlinked]");
2.122 - else
2.123 - buf.append("[")
2.124 - .append("from ").append(vmmethod.getDeclaringClass().getName())
2.125 - .append(" : ").append(getTarget().type())
2.126 - .append(" => ").append(getTarget())
2.127 - .append("]");
2.128 - return buf.toString();
2.129 + return "CallSite"+(target == null ? "" : target.type());
2.130 }
2.131 +
2.132 + /**
2.133 + * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
2.134 + * Produce a method handle equivalent to an invokedynamic instruction
2.135 + * which has been linked to this call site.
2.136 + * <p>If this call site is a {@link ConstantCallSite}, this method
2.137 + * simply returns the call site's target, since that will not change.
2.138 + * <p>Otherwise, this method is equivalent to the following code:
2.139 + * <p><blockquote><pre>
2.140 + * MethodHandle getTarget, invoker, result;
2.141 + * getTarget = MethodHandles.lookup().bind(this, "getTarget", MethodType.methodType(MethodHandle.class));
2.142 + * invoker = MethodHandles.exactInvoker(this.type());
2.143 + * result = MethodHandles.foldArguments(invoker, getTarget)
2.144 + * </pre></blockquote>
2.145 + * @return a method handle which always invokes this call site's current target
2.146 + */
2.147 + public final MethodHandle dynamicInvoker() {
2.148 + if (this instanceof ConstantCallSite)
2.149 + return getTarget(); // will not change dynamically
2.150 + MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, GET_TARGET, this);
2.151 + MethodHandle invoker = MethodHandles.exactInvoker(this.type());
2.152 + return MethodHandles.foldArguments(invoker, getTarget);
2.153 + }
2.154 + private static final MethodHandle GET_TARGET;
2.155 + static {
2.156 + try {
2.157 + GET_TARGET = MethodHandles.Lookup.IMPL_LOOKUP.
2.158 + findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
2.159 + } catch (NoAccessException ignore) {
2.160 + throw new InternalError();
2.161 + }
2.162 + }
2.163 +
2.164 + /** Implementation of {@link MethodHandleProvider} which returns {@code this.dynamicInvoker()}. */
2.165 + public final MethodHandle asMethodHandle() { return dynamicInvoker(); }
2.166 +
2.167 + /** Implementation of {@link MethodHandleProvider}, which returns {@code this.dynamicInvoker().asType(type)}. */
2.168 + public final MethodHandle asMethodHandle(MethodType type) { return dynamicInvoker().asType(type); }
2.169 }
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/src/share/classes/java/dyn/ClassValue.java Wed Nov 10 20:40:19 2010 -0800
3.3 @@ -0,0 +1,173 @@
3.4 +/*
3.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3.7 + *
3.8 + * This code is free software; you can redistribute it and/or modify it
3.9 + * under the terms of the GNU General Public License version 2 only, as
3.10 + * published by the Free Software Foundation. Oracle designates this
3.11 + * particular file as subject to the "Classpath" exception as provided
3.12 + * by Oracle in the LICENSE file that accompanied this code.
3.13 + *
3.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
3.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
3.17 + * version 2 for more details (a copy is included in the LICENSE file that
3.18 + * accompanied this code).
3.19 + *
3.20 + * You should have received a copy of the GNU General Public License version
3.21 + * 2 along with this work; if not, write to the Free Software Foundation,
3.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
3.23 + *
3.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
3.25 + * or visit www.oracle.com if you need additional information or have any
3.26 + * questions.
3.27 + */
3.28 +
3.29 +package java.dyn;
3.30 +
3.31 +import java.util.WeakHashMap;
3.32 +import java.util.concurrent.atomic.AtomicInteger;
3.33 +import java.util.concurrent.atomic.AtomicReference;
3.34 +
3.35 +/**
3.36 + * Lazily associate a computed value with (potentially) every class.
3.37 + * @author John Rose, JSR 292 EG
3.38 + */
3.39 +public abstract class ClassValue<T> {
3.40 + /**
3.41 + * Compute the given class's derived value for this {@code ClassValue}.
3.42 + * <p>
3.43 + * This method will be invoked within the first thread that accesses
3.44 + * the value with the {@link #get}.
3.45 + * <p>
3.46 + * Normally, this method is invoked at most once per class,
3.47 + * but it may be invoked again in case of subsequent invocations
3.48 + * of {@link #remove} followed by {@link #get}.
3.49 + *
3.50 + * @return the computed value for this thread-local
3.51 + */
3.52 + protected abstract T computeValue(Class<?> type);
3.53 +
3.54 + /**
3.55 + * Creates a new class value.
3.56 + */
3.57 + protected ClassValue() {
3.58 + }
3.59 +
3.60 + /**
3.61 + * Returns the value for the given class.
3.62 + * If no value has yet been computed, it is obtained by
3.63 + * by an invocation of the {@link #computeValue} method.
3.64 + * <p>
3.65 + * The actual installation of the value on the class
3.66 + * is performed while the class's synchronization lock
3.67 + * is held. At that point, if racing threads have
3.68 + * computed values, one is chosen, and returned to
3.69 + * all the racing threads.
3.70 + *
3.71 + * @return the current thread's value of this thread-local
3.72 + */
3.73 + public T get(Class<?> type) {
3.74 + ClassValueMap map = getMap(type);
3.75 + if (map != null) {
3.76 + Object x = map.get(this);
3.77 + if (x != null) {
3.78 + return (T) map.unmaskNull(x);
3.79 + }
3.80 + }
3.81 + return setComputedValue(type);
3.82 + }
3.83 +
3.84 + /**
3.85 + * Removes the associated value for the given class.
3.86 + * If this value is subsequently {@linkplain #get read} for the same class,
3.87 + * its value will be reinitialized by invoking its {@link #computeValue} method.
3.88 + * This may result in an additional invocation of the
3.89 + * {@code computeValue} method for the given class.
3.90 + */
3.91 + public void remove(Class<?> type) {
3.92 + ClassValueMap map = getMap(type);
3.93 + if (map != null) {
3.94 + synchronized (map) {
3.95 + map.remove(this);
3.96 + }
3.97 + }
3.98 + }
3.99 +
3.100 + /// Implementation...
3.101 +
3.102 + /** The hash code for this type is based on the identity of the object,
3.103 + * and is well-dispersed for power-of-two tables.
3.104 + */
3.105 + public final int hashCode() { return hashCode; }
3.106 + private final int hashCode = HASH_CODES.getAndAdd(0x61c88647);
3.107 + private static final AtomicInteger HASH_CODES = new AtomicInteger();
3.108 +
3.109 + private static final AtomicInteger STORE_BARRIER = new AtomicInteger();
3.110 +
3.111 + /** Slow path for {@link #get}. */
3.112 + private T setComputedValue(Class<?> type) {
3.113 + ClassValueMap map = getMap(type);
3.114 + if (map == null) {
3.115 + map = initializeMap(type);
3.116 + }
3.117 + T value = computeValue(type);
3.118 + STORE_BARRIER.lazySet(0);
3.119 + // All stores pending from computeValue are completed.
3.120 + synchronized (map) {
3.121 + // Warm up the table with a null entry.
3.122 + map.preInitializeEntry(this);
3.123 + }
3.124 + // All stores pending from table expansion are completed.
3.125 + synchronized (map) {
3.126 + value = (T) map.initializeEntry(this, value);
3.127 + // One might fear a possible race condition here
3.128 + // if the code for map.put has flushed the write
3.129 + // to map.table[*] before the writes to the Map.Entry
3.130 + // are done. This is not possible, since we have
3.131 + // warmed up the table with an empty entry.
3.132 + }
3.133 + return value;
3.134 + }
3.135 +
3.136 + // Replace this map by a per-class slot.
3.137 + private static final WeakHashMap<Class<?>, ClassValueMap> ROOT
3.138 + = new WeakHashMap<Class<?>, ClassValueMap>();
3.139 +
3.140 + private static ClassValueMap getMap(Class<?> type) {
3.141 + return ROOT.get(type);
3.142 + }
3.143 +
3.144 + private static ClassValueMap initializeMap(Class<?> type) {
3.145 + synchronized (ClassValue.class) {
3.146 + ClassValueMap map = ROOT.get(type);
3.147 + if (map == null)
3.148 + ROOT.put(type, map = new ClassValueMap());
3.149 + return map;
3.150 + }
3.151 + }
3.152 +
3.153 + static class ClassValueMap extends WeakHashMap<ClassValue, Object> {
3.154 + /** Make sure this table contains an Entry for the given key, even if it is empty. */
3.155 + void preInitializeEntry(ClassValue key) {
3.156 + if (!this.containsKey(key))
3.157 + this.put(key, null);
3.158 + }
3.159 + /** Make sure this table contains a non-empty Entry for the given key. */
3.160 + Object initializeEntry(ClassValue key, Object value) {
3.161 + Object prior = this.get(key);
3.162 + if (prior != null) {
3.163 + return unmaskNull(prior);
3.164 + }
3.165 + this.put(key, maskNull(value));
3.166 + return value;
3.167 + }
3.168 +
3.169 + Object maskNull(Object x) {
3.170 + return x == null ? this : x;
3.171 + }
3.172 + Object unmaskNull(Object x) {
3.173 + return x == this ? null : x;
3.174 + }
3.175 + }
3.176 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/src/share/classes/java/dyn/ConstantCallSite.java Wed Nov 10 20:40:19 2010 -0800
4.3 @@ -0,0 +1,43 @@
4.4 +/*
4.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4.7 + *
4.8 + * This code is free software; you can redistribute it and/or modify it
4.9 + * under the terms of the GNU General Public License version 2 only, as
4.10 + * published by the Free Software Foundation. Oracle designates this
4.11 + * particular file as subject to the "Classpath" exception as provided
4.12 + * by Oracle in the LICENSE file that accompanied this code.
4.13 + *
4.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
4.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
4.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
4.17 + * version 2 for more details (a copy is included in the LICENSE file that
4.18 + * accompanied this code).
4.19 + *
4.20 + * You should have received a copy of the GNU General Public License version
4.21 + * 2 along with this work; if not, write to the Free Software Foundation,
4.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
4.23 + *
4.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
4.25 + * or visit www.oracle.com if you need additional information or have any
4.26 + * questions.
4.27 + */
4.28 +
4.29 +package java.dyn;
4.30 +
4.31 +/**
4.32 + * A {@code ConstantCallSite} is a {@link CallSite} whose target is permanent, and can never be changed.
4.33 + * The only way to relink an {@code invokedynamic} instruction bound to a {@code ConstantCallSite} is
4.34 + * to invalidate the instruction as a whole.
4.35 + * @author John Rose, JSR 292 EG
4.36 + */
4.37 +public class ConstantCallSite extends CallSite {
4.38 + /** Create a call site with a permanent target. */
4.39 + public ConstantCallSite(MethodHandle target) {
4.40 + super(target);
4.41 + }
4.42 + /** Throw an {@link IllegalArgumentException}, because this kind of call site cannot change its target. */
4.43 + @Override public final void setTarget(MethodHandle ignore) {
4.44 + throw new IllegalArgumentException("ConstantCallSite");
4.45 + }
4.46 +}
5.1 --- a/src/share/classes/java/dyn/InvokeDynamic.java Tue Nov 09 22:53:18 2010 -0800
5.2 +++ b/src/share/classes/java/dyn/InvokeDynamic.java Wed Nov 10 20:40:19 2010 -0800
5.3 @@ -35,7 +35,7 @@
5.4 * The target method is a property of the reified {@linkplain CallSite call site object}
5.5 * which is linked to each active {@code invokedynamic} instruction.
5.6 * The call site object is initially produced by a
5.7 - * {@linkplain java.dyn.Linkage#registerBootstrapMethod(Class, MethodHandle) bootstrap method}
5.8 + * {@linkplain BootstrapMethod bootstrap method}
5.9 * associated with the class whose bytecodes include the dynamic call site.
5.10 * <p>
5.11 * The type {@code InvokeDynamic} has no particular meaning as a
5.12 @@ -45,22 +45,31 @@
5.13 * It may be imported for ease of use.
5.14 * <p>
5.15 * Here are some examples:
5.16 - * <p><blockquote><pre>
5.17 - * Object x; String s; int i;
5.18 - * x = InvokeDynamic.greet("world"); // greet(Ljava/lang/String;)Ljava/lang/Object;
5.19 - * s = InvokeDynamic.<String>hail(x); // hail(Ljava/lang/Object;)Ljava/lang/String;
5.20 - * InvokeDynamic.<void>cogito(); // cogito()V
5.21 - * i = InvokeDynamic.<int>#"op:+"(2, 3); // "op:+"(II)I
5.22 - * </pre></blockquote>
5.23 +<blockquote><pre><!-- see indy-demo/src/JavaDocExamples.java -->
5.24 +@BootstrapMethod(value=Here.class, name="bootstrapDynamic")
5.25 +static void example() throws Throwable {
5.26 + Object x; String s; int i;
5.27 + x = InvokeDynamic.greet("world"); // greet(Ljava/lang/String;)Ljava/lang/Object;
5.28 + s = (String) InvokeDynamic.hail(x); // hail(Ljava/lang/Object;)Ljava/lang/String;
5.29 + InvokeDynamic.cogito(); // cogito()V
5.30 + i = (int) InvokeDynamic.#"op:+"(2, 3); // "op:+"(II)I
5.31 +}
5.32 +static MethodHandle bootstrapDynamic(Class caller, String name, MethodType type) { ... }
5.33 +</pre></blockquote>
5.34 * Each of the above calls generates a single invokedynamic instruction
5.35 * with the name-and-type descriptors indicated in the comments.
5.36 + * <p>
5.37 * The argument types are taken directly from the actual arguments,
5.38 - * while the return type is taken from the type parameter.
5.39 - * (This type parameter may be a primtive, and it defaults to {@code Object}.)
5.40 + * while the return type corresponds to the target of the assignment.
5.41 + * (Currently, the return type must be given as a false type parameter.
5.42 + * This type parameter is an irregular use of the generic type syntax,
5.43 + * and is likely to change in favor of a convention based on target typing.)
5.44 + * <p>
5.45 * The final example uses a special syntax for uttering non-Java names.
5.46 * Any name legal to the JVM may be given between the double quotes.
5.47 + * <p>
5.48 * None of these calls is complete without a bootstrap method,
5.49 - * which must be registered by the static initializer of the enclosing class.
5.50 + * which must be declared for the enclosing class or method.
5.51 * @author John Rose, JSR 292 EG
5.52 */
5.53 @MethodHandle.PolymorphicSignature
6.1 --- a/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java Tue Nov 09 22:53:18 2010 -0800
6.2 +++ b/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java Wed Nov 10 20:40:19 2010 -0800
6.3 @@ -28,15 +28,11 @@
6.4 /**
6.5 * Thrown to indicate that an {@code invokedynamic} instruction has
6.6 * failed to find its
6.7 - * {@linkplain Linkage#registerBootstrapMethod(Class, MethodHandle) bootstrap method},
6.8 + * {@linkplain BootstrapMethod bootstrap method},
6.9 * or the bootstrap method has
6.10 * failed to provide a
6.11 * {@linkplain CallSite} call site with a non-null {@linkplain MethodHandle target}
6.12 * of the correct {@linkplain MethodType method type}.
6.13 - * <p>
6.14 - * The bootstrap method must have been declared during a class's initialization
6.15 - * by a call to one of the overloadings of
6.16 - * {@link Linkage#registerBootstrapMethod registerBootstrapMethod}.
6.17 *
6.18 * @author John Rose, JSR 292 EG
6.19 * @since 1.7
7.1 --- a/src/share/classes/java/dyn/JavaMethodHandle.java Tue Nov 09 22:53:18 2010 -0800
7.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
7.3 @@ -1,237 +0,0 @@
7.4 -/*
7.5 - * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
7.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7.7 - *
7.8 - * This code is free software; you can redistribute it and/or modify it
7.9 - * under the terms of the GNU General Public License version 2 only, as
7.10 - * published by the Free Software Foundation. Oracle designates this
7.11 - * particular file as subject to the "Classpath" exception as provided
7.12 - * by Oracle in the LICENSE file that accompanied this code.
7.13 - *
7.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
7.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7.17 - * version 2 for more details (a copy is included in the LICENSE file that
7.18 - * accompanied this code).
7.19 - *
7.20 - * You should have received a copy of the GNU General Public License version
7.21 - * 2 along with this work; if not, write to the Free Software Foundation,
7.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7.23 - *
7.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7.25 - * or visit www.oracle.com if you need additional information or have any
7.26 - * questions.
7.27 - */
7.28 -
7.29 -package java.dyn;
7.30 -
7.31 -import sun.dyn.Access;
7.32 -
7.33 -/**
7.34 - * A Java method handle is a deprecated proposal for extending
7.35 - * the basic method handle type with additional
7.36 - * programmer defined methods and fields.
7.37 - * Its behavior as a method handle is determined at instance creation time,
7.38 - * by providing the new instance with an "entry point" method handle
7.39 - * to handle calls. This entry point must accept a leading argument
7.40 - * whose type is the Java method handle itself or a supertype, and the
7.41 - * entry point is always called with the Java method handle itself as
7.42 - * the first argument. This is similar to ordinary virtual methods, which also
7.43 - * accept the receiver object {@code this} as an implicit leading argument.
7.44 - * The {@code MethodType} of the Java method handle is the same as that
7.45 - * of the entry point method handle, with the leading parameter type
7.46 - * omitted.
7.47 - * <p>
7.48 - * Here is an example of usage, creating a hybrid object/functional datum:
7.49 - * <p><blockquote><pre>
7.50 - * class Greeter extends JavaMethodHandle {
7.51 - * private String greeting = "hello";
7.52 - * public void setGreeting(String s) { greeting = s; }
7.53 - * public void run() { System.out.println(greeting+", "+greetee); }
7.54 - * private final String greetee;
7.55 - * Greeter(String greetee) {
7.56 - * super(RUN); // alternatively, super("run")
7.57 - * this.greetee = greetee;
7.58 - * }
7.59 - * // the entry point function is computed once:
7.60 - * private static final MethodHandle RUN
7.61 - * = MethodHandles.lookup().findVirtual(Greeter.class, "run",
7.62 - * MethodType.make(void.class));
7.63 - * }
7.64 - * // class Main { public static void main(String... av) { ...
7.65 - * Greeter greeter = new Greeter("world");
7.66 - * greeter.run(); // prints "hello, world"
7.67 - * // Statically typed method handle invocation (most direct):
7.68 - * MethodHandle mh = greeter;
7.69 - * mh.<void>invokeExact(); // also prints "hello, world"
7.70 - * // Dynamically typed method handle invocation:
7.71 - * MethodHandles.invokeExact(greeter); // also prints "hello, world"
7.72 - * greeter.setGreeting("howdy");
7.73 - * mh.invokeExact(); // prints "howdy, world" (object-like mutable behavior)
7.74 - * </pre></blockquote>
7.75 - * <p>
7.76 - * In the example of {@code Greeter}, the method {@code run} provides the entry point.
7.77 - * The entry point need not be a constant value; it may be independently
7.78 - * computed in each call to the constructor. The entry point does not
7.79 - * even need to be a method on the {@code Greeter} class, though
7.80 - * that is the typical case.
7.81 - * <p>
7.82 - * The entry point may also be provided symbolically, in which case the the
7.83 - * {@code JavaMethodHandle} constructor performs the lookup of the entry point.
7.84 - * This makes it possible to use {@code JavaMethodHandle} to create an anonymous
7.85 - * inner class:
7.86 - * <p><blockquote><pre>
7.87 - * // We can also do this with symbolic names and/or inner classes:
7.88 - * MethodHandles.invokeExact(new JavaMethodHandle("yow") {
7.89 - * void yow() { System.out.println("yow, world"); }
7.90 - * });
7.91 - * </pre></blockquote>
7.92 - * <p>
7.93 - * Here is similar lower-level code which works in terms of a bound method handle.
7.94 - * <p><blockquote><pre>
7.95 - * class Greeter {
7.96 - * public void run() { System.out.println("hello, "+greetee); }
7.97 - * private final String greetee;
7.98 - * Greeter(String greetee) { this.greetee = greetee; }
7.99 - * // the entry point function is computed once:
7.100 - * private static final MethodHandle RUN
7.101 - * = MethodHandles.findVirtual(Greeter.class, "run",
7.102 - * MethodType.make(void.class));
7.103 - * }
7.104 - * // class Main { public static void main(String... av) { ...
7.105 - * Greeter greeter = new Greeter("world");
7.106 - * greeter.run(); // prints "hello, world"
7.107 - * MethodHandle mh = MethodHanndles.insertArgument(Greeter.RUN, 0, greeter);
7.108 - * mh.invokeExact(); // also prints "hello, world"
7.109 - * </pre></blockquote>
7.110 - * Note that the method handle must be separately created as a view on the base object.
7.111 - * This increases footprint, complexity, and dynamic indirections.
7.112 - * <p>
7.113 - * Here is a pure functional value expressed most concisely as an anonymous inner class:
7.114 - * <p><blockquote><pre>
7.115 - * // class Main { public static void main(String... av) { ...
7.116 - * final String greetee = "world";
7.117 - * MethodHandle greeter = new JavaMethodHandle("run") {
7.118 - * private void run() { System.out.println("hello, "+greetee); }
7.119 - * }
7.120 - * greeter.invokeExact(); // prints "hello, world"
7.121 - * </pre></blockquote>
7.122 - * <p>
7.123 - * Here is an abstract parameterized lvalue, efficiently expressed as a subtype of MethodHandle,
7.124 - * and instantiated as an anonymous class. The data structure is a handle to 1-D array,
7.125 - * with a specialized index type (long). It is created by inner class, and uses
7.126 - * signature-polymorphic APIs throughout.
7.127 - * <p><blockquote><pre>
7.128 - * abstract class AssignableMethodHandle extends JavaMethodHandle {
7.129 - * private final MethodHandle setter;
7.130 - * public MethodHandle setter() { return setter; }
7.131 - * public AssignableMethodHandle(String get, String set) {
7.132 - * super(get);
7.133 - * MethodType getType = this.type();
7.134 - * MethodType setType = getType.insertParameterType(getType.parameterCount(), getType.returnType()).changeReturnType(void.class);
7.135 - * this.setter = MethodHandles.publicLookup().bind(this, set, setType);
7.136 - * }
7.137 - * }
7.138 - * // class Main { public static void main(String... av) { ...
7.139 - * final Number[] stuff = { 123, 456 };
7.140 - * AssignableMethodHandle stuffPtr = new AssignableMethodHandle("get", "set") {
7.141 - * public Number get(long i) { return stuff[(int)i]; }
7.142 - * public void set(long i, Object x) { stuff[(int)i] = x; }
7.143 - * }
7.144 - * int x = (Integer) stuffPtr.<Number>invokeExact(1L); // 456
7.145 - * stuffPtr.setter().<void>invokeExact(0L, (Number) 789); // replaces 123 with 789
7.146 - * </pre></blockquote>
7.147 - * @see MethodHandle
7.148 - * @deprecated The JSR 292 EG intends to replace {@code JavaMethodHandle} with
7.149 - * an interface-based API for mixing method handle behavior with other classes.
7.150 - * @author John Rose, JSR 292 EG
7.151 - */
7.152 -public abstract class JavaMethodHandle
7.153 - // Note: This is an implementation inheritance hack, and will be removed
7.154 - // with a JVM change which moves the required hidden behavior onto this class.
7.155 - extends sun.dyn.BoundMethodHandle
7.156 -{
7.157 - private static final Access IMPL_TOKEN = Access.getToken();
7.158 -
7.159 - /**
7.160 - * When creating a {@code JavaMethodHandle}, the actual method handle
7.161 - * invocation behavior will be delegated to the specified {@code entryPoint}.
7.162 - * This may be any method handle which can take the newly constructed object
7.163 - * as a leading parameter.
7.164 - * <p>
7.165 - * The method handle type of {@code this} (i.e, the fully constructed object)
7.166 - * will be {@code entryPoint}, minus the leading argument.
7.167 - * The leading argument will be bound to {@code this} on every method
7.168 - * handle invocation.
7.169 - * @param entryPoint the method handle to handle calls
7.170 - */
7.171 - protected JavaMethodHandle(MethodHandle entryPoint) {
7.172 - super(entryPoint);
7.173 - }
7.174 -
7.175 - /**
7.176 - * Create a method handle whose entry point is a non-static method
7.177 - * visible in the exact (most specific) class of
7.178 - * the newly constructed object.
7.179 - * <p>
7.180 - * The method is specified by name and type, as if via this expression:
7.181 - * {@code MethodHandles.lookup().findVirtual(this.getClass(), name, type)}.
7.182 - * The class defining the method might be an anonymous inner class.
7.183 - * <p>
7.184 - * The method handle type of {@code this} (i.e, the fully constructed object)
7.185 - * will be the given method handle type.
7.186 - * A call to {@code this} will invoke the selected method.
7.187 - * The receiver argument will be bound to {@code this} on every method
7.188 - * handle invocation.
7.189 - * <p>
7.190 - * <i>Rationale:</i>
7.191 - * Although this constructor may seem to be a mere luxury,
7.192 - * it is not subsumed by the more general constructor which
7.193 - * takes any {@code MethodHandle} as the entry point argument.
7.194 - * In order to convert an entry point name to a method handle,
7.195 - * the self-class of the object is required (in order to do
7.196 - * the lookup). The self-class, in turn, is generally not
7.197 - * available at the time of the constructor invocation,
7.198 - * due to the rules of Java and the JVM verifier.
7.199 - * One cannot call {@code this.getClass()}, because
7.200 - * the value of {@code this} is inaccessible at the point
7.201 - * of the constructor call. (Changing this would require
7.202 - * change to the Java language, verifiers, and compilers.)
7.203 - * In particular, this constructor allows {@code JavaMethodHandle}s
7.204 - * to be created in combination with the anonymous inner class syntax.
7.205 - * @param entryPointName the name of the entry point method
7.206 - * @param type (optional) the desired type of the method handle
7.207 - */
7.208 - protected JavaMethodHandle(String entryPointName, MethodType type) {
7.209 - super(entryPointName, type, true);
7.210 -
7.211 - }
7.212 -
7.213 - /**
7.214 - * Create a method handle whose entry point is a non-static method
7.215 - * visible in the exact (most specific) class of
7.216 - * the newly constructed object.
7.217 - * <p>
7.218 - * The method is specified only by name.
7.219 - * There must be exactly one method of that name visible in the object class,
7.220 - * either inherited or locally declared.
7.221 - * (That is, the method must not be overloaded.)
7.222 - * <p>
7.223 - * The method handle type of {@code this} (i.e, the fully constructed object)
7.224 - * will be the same as the type of the selected non-static method.
7.225 - * The receiver argument will be bound to {@code this} on every method
7.226 - * handle invocation.
7.227 - * <p>ISSUE: This signature wildcarding feature does not correspond to
7.228 - * any MethodHandles.Lookup API element. Can we eliminate it?
7.229 - * Alternatively, it is useful for naming non-overloaded methods.
7.230 - * Shall we make type arguments optional in the Lookup methods,
7.231 - * throwing an error in cases of ambiguity?
7.232 - * <p>
7.233 - * For this method's rationale, see the documentation
7.234 - * for {@link #JavaMethodHandle(String,MethodType)}.
7.235 - * @param entryPointName the name of the entry point method
7.236 - */
7.237 - protected JavaMethodHandle(String entryPointName) {
7.238 - super(entryPointName, (MethodType) null, false);
7.239 - }
7.240 -}
8.1 --- a/src/share/classes/java/dyn/Linkage.java Tue Nov 09 22:53:18 2010 -0800
8.2 +++ b/src/share/classes/java/dyn/Linkage.java Wed Nov 10 20:40:19 2010 -0800
8.3 @@ -25,7 +25,6 @@
8.4
8.5 package java.dyn;
8.6
8.7 -import java.lang.annotation.Annotation;
8.8 import java.dyn.MethodHandles.Lookup;
8.9 import java.util.WeakHashMap;
8.10 import sun.dyn.Access;
8.11 @@ -56,11 +55,7 @@
8.12 * <li>the class containing the {@code invokedynamic} instruction, for which the bootstrap method was registered
8.13 * <li>the name of the method being invoked (a {@link String})
8.14 * <li>the type of the method being invoked (a {@link MethodType})
8.15 - * <li><em>TBD</em> optionally, an unordered array of {@link Annotation}s attached to the call site
8.16 - * <em>(Until this feature is implemented, this will always receive an empty array.)</em>
8.17 * </ul>
8.18 - * <em>(TBD: The final argument type may be missing from the method handle's type.
8.19 - * Additional arguments may be added in the future.)</em>
8.20 * The bootstrap method acts as a factory method which accepts the given arguments
8.21 * and returns a {@code CallSite} object (possibly of a subclass of {@code CallSite}).
8.22 * <p>
8.23 @@ -86,6 +81,7 @@
8.24 * or is already running in another thread
8.25 * @exception SecurityException if there is a security manager installed,
8.26 * and a {@link LinkagePermission} check fails for "registerBootstrapMethod"
8.27 + * @deprecated Use @{@link BootstrapMethod} annotations instead
8.28 */
8.29 public static
8.30 void registerBootstrapMethod(Class callerClass, MethodHandle bootstrapMethod) {
8.31 @@ -97,14 +93,9 @@
8.32
8.33 static private void checkBSM(MethodHandle mh) {
8.34 if (mh == null) throw newIllegalArgumentException("null bootstrap method");
8.35 - if (mh.type() == BOOTSTRAP_METHOD_TYPE_2)
8.36 - // For now, always pass an empty array for the Annotations argument
8.37 - mh = MethodHandles.insertArguments(mh, BOOTSTRAP_METHOD_TYPE_2.parameterCount()-1,
8.38 - (Object)NO_ANNOTATIONS);
8.39 if (mh.type() == BOOTSTRAP_METHOD_TYPE) return;
8.40 throw new WrongMethodTypeException(mh.toString());
8.41 }
8.42 - static private final Annotation[] NO_ANNOTATIONS = { };
8.43
8.44 /**
8.45 * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
8.46 @@ -115,6 +106,7 @@
8.47 * @throws NoSuchMethodException if there is no such method
8.48 * @throws IllegalStateException if the caller class's static initializer
8.49 * has already run, or is already running in another thread
8.50 + * @deprecated Use @{@link BootstrapMethod} annotations instead
8.51 */
8.52 public static
8.53 void registerBootstrapMethod(Class<?> runtime, String name) {
8.54 @@ -131,6 +123,7 @@
8.55 * @throws IllegalArgumentException if there is no such method
8.56 * @throws IllegalStateException if the caller class's static initializer
8.57 * has already run, or is already running in another thread
8.58 + * @deprecated Use @{@link BootstrapMethod} annotations instead
8.59 */
8.60 public static
8.61 void registerBootstrapMethod(String name) {
8.62 @@ -142,18 +135,10 @@
8.63 void registerBootstrapMethodLookup(Class<?> callerClass, Class<?> runtime, String name) {
8.64 Lookup lookup = new Lookup(IMPL_TOKEN, callerClass);
8.65 MethodHandle bootstrapMethod;
8.66 - // Try both types. TBD
8.67 try {
8.68 - bootstrapMethod = lookup.findStatic(runtime, name, BOOTSTRAP_METHOD_TYPE_2);
8.69 + bootstrapMethod = lookup.findStatic(runtime, name, BOOTSTRAP_METHOD_TYPE);
8.70 } catch (NoAccessException ex) {
8.71 - bootstrapMethod = null;
8.72 - }
8.73 - if (bootstrapMethod == null) {
8.74 - try {
8.75 - bootstrapMethod = lookup.findStatic(runtime, name, BOOTSTRAP_METHOD_TYPE);
8.76 - } catch (NoAccessException ex) {
8.77 - throw new IllegalArgumentException("no such bootstrap method in "+runtime+": "+name, ex);
8.78 - }
8.79 + throw new IllegalArgumentException("no such bootstrap method in "+runtime+": "+name, ex);
8.80 }
8.81 checkBSM(bootstrapMethod);
8.82 MethodHandleImpl.registerBootstrap(IMPL_TOKEN, callerClass, bootstrapMethod);
8.83 @@ -172,6 +157,7 @@
8.84 * and the immediate caller of this method is not in the same
8.85 * package as the caller class
8.86 * and a {@link LinkagePermission} check fails for "getBootstrapMethod"
8.87 + * @deprecated
8.88 */
8.89 public static
8.90 MethodHandle getBootstrapMethod(Class callerClass) {
8.91 @@ -188,10 +174,6 @@
8.92 public static final MethodType BOOTSTRAP_METHOD_TYPE
8.93 = MethodType.methodType(CallSite.class,
8.94 Class.class, String.class, MethodType.class);
8.95 - static final MethodType BOOTSTRAP_METHOD_TYPE_2
8.96 - = MethodType.methodType(CallSite.class,
8.97 - Class.class, String.class, MethodType.class,
8.98 - Annotation[].class);
8.99
8.100 /**
8.101 * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
9.1 --- a/src/share/classes/java/dyn/LinkagePermission.java Tue Nov 09 22:53:18 2010 -0800
9.2 +++ b/src/share/classes/java/dyn/LinkagePermission.java Wed Nov 10 20:40:19 2010 -0800
9.3 @@ -31,6 +31,7 @@
9.4 import java.util.StringTokenizer;
9.5
9.6 /**
9.7 + * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
9.8 * This class is for managing runtime permission checking for
9.9 * operations performed by methods in the {@link Linkage} class.
9.10 * Like a {@link RuntimePermission}, on which it is modeled,
9.11 @@ -52,13 +53,6 @@
9.12 * </tr>
9.13 *
9.14 * <tr>
9.15 - * <td>registerBootstrapMethod.{class name}</td>
9.16 - * <td>Specifying a bootstrap method for {@code invokedynamic} instructions within a class of the given name</td>
9.17 - * <td>An attacker could attempt to attach a bootstrap method to a class which
9.18 - * has just been loaded, thus gaining control of its {@code invokedynamic} calls.</td>
9.19 - * </tr>
9.20 - *
9.21 - * <tr>
9.22 * <td>invalidateAll</td>
9.23 * <td>Force the relinking of invokedynamic call sites everywhere.</td>
9.24 * <td>This could allow an attacker to slow down the system,
9.25 @@ -73,8 +67,9 @@
9.26 * <td>See {@code invalidateAll}.</td>
9.27 * </tr>
9.28 * </table>
9.29 + * <p>ISSUE: Is this still needed?
9.30 *
9.31 - * @see java.security.RuntimePermission
9.32 + * @see java.lang.RuntimePermission
9.33 * @see java.lang.SecurityManager
9.34 *
9.35 * @author John Rose, JSR 292 EG
9.36 @@ -86,7 +81,7 @@
9.37 /**
9.38 * Create a new LinkagePermission with the given name.
9.39 * The name is the symbolic name of the LinkagePermission, such as
9.40 - * "registerBootstrapMethod", "invalidateCallerClass.*", etc. An asterisk
9.41 + * "invalidateCallerClass.*", etc. An asterisk
9.42 * may appear at the end of the name, following a ".", or by itself, to
9.43 * signify a wildcard match.
9.44 *
10.1 --- a/src/share/classes/java/dyn/MethodHandle.java Tue Nov 09 22:53:18 2010 -0800
10.2 +++ b/src/share/classes/java/dyn/MethodHandle.java Wed Nov 10 20:40:19 2010 -0800
10.3 @@ -1,5 +1,5 @@
10.4 /*
10.5 - * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
10.6 + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
10.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10.8 *
10.9 * This code is free software; you can redistribute it and/or modify it
10.10 @@ -36,11 +36,13 @@
10.11 /**
10.12 * A method handle is a typed, directly executable reference to a method,
10.13 * constructor, field, or similar low-level operation, with optional
10.14 - * conversion or substitution of arguments or return values.
10.15 + * transformations of arguments or return values.
10.16 + * (These transformations include conversion, insertion, deletion,
10.17 + * substitution. See the methods of this class and of {@link MethodHandles}.)
10.18 * <p>
10.19 * Method handles are strongly typed according to signature.
10.20 * They are not distinguished by method name or enclosing class.
10.21 - * A method handle must be invoked under a signature which exactly matches
10.22 + * A method handle must be invoked under a signature which matches
10.23 * the method handle's own {@link MethodType method type}.
10.24 * <p>
10.25 * Every method handle confesses its type via the {@code type} accessor.
10.26 @@ -174,9 +176,10 @@
10.27 * merely a documentation convention. These type parameters do
10.28 * not play a role in type-checking method handle invocations.
10.29 * <p>
10.30 - * Note: Like classes and strings, method handles that correspond directly
10.31 - * to fields and methods can be represented directly as constants to be
10.32 - * loaded by {@code ldc} bytecodes.
10.33 + * Like classes and strings, method handles that correspond to accessible
10.34 + * fields, methods, and constructors can be represented directly
10.35 + * in a class file's constant pool as constants to be loaded by {@code ldc} bytecodes.
10.36 + * Loading such a constant causes the component classes of its type to be loaded as necessary.
10.37 *
10.38 * @see MethodType
10.39 * @see MethodHandles
10.40 @@ -186,6 +189,7 @@
10.41 // Note: This is an implementation inheritance hack, and will be removed
10.42 // with a JVM change which moves the required hidden state onto this class.
10.43 extends MethodHandleImpl
10.44 + implements MethodHandleProvider
10.45 {
10.46 private static Access IMPL_TOKEN = Access.getToken();
10.47
10.48 @@ -197,7 +201,7 @@
10.49 * those methods which are signature polymorphic.
10.50 */
10.51 @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD,java.lang.annotation.ElementType.TYPE})
10.52 - @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS)
10.53 + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
10.54 @interface PolymorphicSignature { }
10.55
10.56 private MethodType type;
10.57 @@ -274,10 +278,14 @@
10.58 * and performing simple conversions for arguments and return types.
10.59 * The signature at the call site of {@code invokeGeneric} must
10.60 * have the same arity as this method handle's {@code type}.
10.61 - * The same conversions are allowed on arguments or return values as are supported by
10.62 - * by {@link MethodHandles#convertArguments}.
10.63 + * <p>
10.64 * If the call site signature exactly matches this method handle's {@code type},
10.65 * the call proceeds as if by {@link #invokeExact}.
10.66 + * <p>
10.67 + * Otherwise, the call proceeds as if this method handle were first
10.68 + * adjusted by calling {@link #asType} to adjust this method handle
10.69 + * to the required type, and then the call proceeds as if by
10.70 + * {@link #invokeExact} on the adjusted method handle.
10.71 */
10.72 public final native @PolymorphicSignature <R,A> R invokeGeneric(A... args) throws Throwable;
10.73
10.74 @@ -538,4 +546,10 @@
10.75 public final MethodHandle bindTo(Object x) {
10.76 return MethodHandles.insertArguments(this, 0, x);
10.77 }
10.78 +
10.79 + /** Implementation of {@link MethodHandleProvider}, which returns {@code this}. */
10.80 + public final MethodHandle asMethodHandle() { return this; }
10.81 +
10.82 + /** Implementation of {@link MethodHandleProvider}, which returns {@code this.asType(type)}. */
10.83 + public final MethodHandle asMethodHandle(MethodType type) { return this.asType(type); }
10.84 }
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/src/share/classes/java/dyn/MethodHandleProvider.java Wed Nov 10 20:40:19 2010 -0800
11.3 @@ -0,0 +1,80 @@
11.4 +/*
11.5 + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11.7 + *
11.8 + * This code is free software; you can redistribute it and/or modify it
11.9 + * under the terms of the GNU General Public License version 2 only, as
11.10 + * published by the Free Software Foundation. Oracle designates this
11.11 + * particular file as subject to the "Classpath" exception as provided
11.12 + * by Oracle in the LICENSE file that accompanied this code.
11.13 + *
11.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
11.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11.17 + * version 2 for more details (a copy is included in the LICENSE file that
11.18 + * accompanied this code).
11.19 + *
11.20 + * You should have received a copy of the GNU General Public License version
11.21 + * 2 along with this work; if not, write to the Free Software Foundation,
11.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
11.23 + *
11.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
11.25 + * or visit www.oracle.com if you need additional information or have any
11.26 + * questions.
11.27 + */
11.28 +
11.29 +package java.dyn;
11.30 +
11.31 +/**
11.32 + * An interface for an object to provide a target {@linkplain MethodHandle method handle} to a {@code invokedynamic} instruction.
11.33 + * There are many function-like objects in various Java APIs.
11.34 + * This interface provides a standard way for such function-like objects to be bound
11.35 + * to a dynamic call site, by providing a view of their behavior in the form of a low-level method handle.
11.36 + * <p>
11.37 + * The type {@link MethodHandle} is a concrete class whose implementation
11.38 + * hierarchy (if any) may be tightly coupled to the underlying JVM implementation.
11.39 + * It cannot also serve as a base type for user-defined functional APIs.
11.40 + * For this reason, {@code MethodHandle} cannot be subclassed to add new
11.41 + * behavior to method handles. But this interface can be used to provide
11.42 + * a link between a user-defined function and the {@code invokedynamic}
11.43 + * instruction and the method handle API.
11.44 + */
11.45 +public interface MethodHandleProvider {
11.46 + /** Produce a method handle which will serve as a behavioral proxy for the current object.
11.47 + * The type and invocation behavior of the proxy method handle are user-defined,
11.48 + * and should have some relation to the intended meaning of the original object itself.
11.49 + * <p>
11.50 + * The current object may have a changeable behavior.
11.51 + * For example, {@link CallSite} has a {@code setTarget} method which changes its invocation.
11.52 + * In such a case, it is <em>incorrect</em> for {@code asMethodHandle} to return
11.53 + * a method handle whose behavior may diverge from that of the current object.
11.54 + * Rather, the returned method handle must stably and permanently access
11.55 + * the behavior of the current object, even if that behavior is changeable.
11.56 + * <p>
11.57 + * The reference identity of the proxy method handle is not guaranteed to
11.58 + * have any particular relation to the reference identity of the object.
11.59 + * In particular, several objects with the same intended meaning could
11.60 + * share a common method handle, or the same object could return different
11.61 + * method handles at different times. In the latter case, the different
11.62 + * method handles should have the same type and invocation behavior,
11.63 + * and be usable from any thread at any time.
11.64 + * In particular, if a MethodHandleProvider is bound to an <code>invokedynamic</code>
11.65 + * call site, the proxy method handle extracted at the time of binding
11.66 + * will be used for an unlimited time, until the call site is rebound.
11.67 + * <p>
11.68 + * The type {@link MethodHandle} itself implements {@code MethodHandleProvider}, and
11.69 + * for this method simply returns {@code this}.
11.70 + */
11.71 + public MethodHandle asMethodHandle();
11.72 +
11.73 + /** Produce a method handle of a given type which will serve as a behavioral proxy for the current object.
11.74 + * As for the no-argument version {@link #asMethodHandle()}, the invocation behavior of the
11.75 + * proxy method handle is user-defined. But the type must be the given type,
11.76 + * or else a {@link WrongMethodTypeException} must be thrown.
11.77 + * <p>
11.78 + * If the current object somehow represents a variadic or overloaded behavior,
11.79 + * the method handle returned for a given type might represent only a subset of
11.80 + * the current object's repertoire of behaviors, which correspond to that type.
11.81 + */
11.82 + public MethodHandle asMethodHandle(MethodType type) throws WrongMethodTypeException;
11.83 +}
12.1 --- a/src/share/classes/java/dyn/MethodHandles.java Tue Nov 09 22:53:18 2010 -0800
12.2 +++ b/src/share/classes/java/dyn/MethodHandles.java Wed Nov 10 20:40:19 2010 -0800
12.3 @@ -25,15 +25,12 @@
12.4
12.5 package java.dyn;
12.6
12.7 -import java.lang.reflect.Constructor;
12.8 +import java.lang.reflect.*;
12.9 import sun.dyn.Access;
12.10 import sun.dyn.MemberName;
12.11 import sun.dyn.MethodHandleImpl;
12.12 import sun.dyn.util.VerifyAccess;
12.13 import sun.dyn.util.Wrapper;
12.14 -import java.lang.reflect.Field;
12.15 -import java.lang.reflect.Method;
12.16 -import java.lang.reflect.Modifier;
12.17 import java.util.List;
12.18 import java.util.ArrayList;
12.19 import java.util.Arrays;
12.20 @@ -81,6 +78,14 @@
12.21 * Return a {@link Lookup lookup object} which is trusted minimally.
12.22 * It can only be used to create method handles to
12.23 * publicly accessible fields and methods.
12.24 + * <p>
12.25 + * As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class}
12.26 + * of this lookup object will be {@link java.lang.Object}.
12.27 + * <p>
12.28 + * The lookup class can be changed to any other class {@code C} using an expression of the form
12.29 + * {@linkplain Lookup#in <code>publicLookup().in(C.class)</code>}.
12.30 + * Since all classes have equal access to public names,
12.31 + * such a change would confer no new access rights.
12.32 */
12.33 public static Lookup publicLookup() {
12.34 return Lookup.PUBLIC_LOOKUP;
12.35 @@ -90,9 +95,10 @@
12.36 * A <em>lookup object</em> is a factory for creating method handles,
12.37 * when the creation requires access checking.
12.38 * Method handles do not perform
12.39 - * access checks when they are called; this is a major difference
12.40 + * access checks when they are called, but rather when they are created.
12.41 + * (This is a major difference
12.42 * from reflective {@link Method}, which performs access checking
12.43 - * against every caller, on every call.
12.44 + * against every caller, on every call.)
12.45 * Therefore, method handle access
12.46 * restrictions must be enforced when a method handle is created.
12.47 * The caller class against which those restrictions are enforced
12.48 @@ -107,7 +113,7 @@
12.49 * It may then use this factory to create method handles on
12.50 * all of its methods, including private ones.
12.51 * It may also delegate the lookup (e.g., to a metaobject protocol)
12.52 - * by passing the {@code Lookup} object to other code.
12.53 + * by passing the lookup object to other code.
12.54 * If this other code creates method handles, they will be access
12.55 * checked against the original lookup class, and not with any higher
12.56 * privileges.
12.57 @@ -125,23 +131,28 @@
12.58 * It can also fail if a security manager is installed and refuses
12.59 * access. In any of these cases, an exception will be
12.60 * thrown from the attempted lookup.
12.61 + * <p>
12.62 * In general, the conditions under which a method handle may be
12.63 * created for a method {@code M} are exactly as restrictive as the conditions
12.64 * under which the lookup class could have compiled a call to {@code M}.
12.65 - * At least some of these error conditions are likely to be
12.66 - * represented by checked exceptions in the final version of this API.
12.67 + * This rule is applied even if the Java compiler might have created
12.68 + * an wrapper method to access a private method of another class
12.69 + * in the same top-level declaration.
12.70 + * For example, a lookup object created for a nested class {@code C.D}
12.71 + * can access private members within other related classes such as
12.72 + * {@code C}, {@code C.D.E}, or {@code C.B}.
12.73 */
12.74 public static final
12.75 class Lookup {
12.76 /** The class on behalf of whom the lookup is being performed. */
12.77 private final Class<?> lookupClass;
12.78
12.79 - /** The allowed sorts of members which may be looked up (public, etc.), with STRICT for package. */
12.80 + /** The allowed sorts of members which may be looked up (public, etc.), with STATIC for package. */
12.81 private final int allowedModes;
12.82
12.83 private static final int
12.84 PUBLIC = Modifier.PUBLIC,
12.85 - PACKAGE = Modifier.STRICT,
12.86 + PACKAGE = Modifier.STATIC,
12.87 PROTECTED = Modifier.PROTECTED,
12.88 PRIVATE = Modifier.PRIVATE,
12.89 ALL_MODES = (PUBLIC | PACKAGE | PROTECTED | PRIVATE),
12.90 @@ -155,8 +166,10 @@
12.91 /** Which class is performing the lookup? It is this class against
12.92 * which checks are performed for visibility and access permissions.
12.93 * <p>
12.94 - * This value is null if and only if this lookup was produced
12.95 - * by {@link MethodHandles#publicLookup}.
12.96 + * The class implies a maximum level of access permission,
12.97 + * but the permissions may be additionally limited by the bitmask
12.98 + * {@link #lookupModes}, which controls whether non-public members
12.99 + * can be accessed.
12.100 */
12.101 public Class<?> lookupClass() {
12.102 return lookupClass;
12.103 @@ -168,10 +181,15 @@
12.104 }
12.105
12.106 /** Which types of members can this lookup object produce?
12.107 - * The result is a bit-mask of the modifier bits PUBLIC, PROTECTED, PRIVATE, and STRICT.
12.108 - * The modifier bit STRICT stands in for the (non-existent) package protection mode.
12.109 + * The result is a bit-mask of the {@link Modifier} bits
12.110 + * {@linkplain Modifier#PUBLIC PUBLIC (0x01)},
12.111 + * {@linkplain Modifier#PROTECTED PROTECTED (0x02)},
12.112 + * {@linkplain Modifier#PRIVATE PRIVATE (0x04)},
12.113 + * and {@linkplain Modifier#STATIC STATIC (0x08)}.
12.114 + * The modifier bit {@code STATIC} stands in for the package protection mode,
12.115 + * which does not have an explicit modifier bit.
12.116 */
12.117 - int lookupModes() {
12.118 + public int lookupModes() {
12.119 return allowedModes & ALL_MODES;
12.120 }
12.121
12.122 @@ -621,32 +639,32 @@
12.123
12.124 /// Helper methods, all package-private.
12.125
12.126 - MemberName resolveOrFail(Class<?> refc, String name, Class<?> type, boolean isStatic) {
12.127 + MemberName resolveOrFail(Class<?> refc, String name, Class<?> type, boolean isStatic) throws NoAccessException {
12.128 checkSymbolicClass(refc); // do this before attempting to resolve
12.129 int mods = (isStatic ? Modifier.STATIC : 0);
12.130 return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull());
12.131 }
12.132
12.133 - MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic) {
12.134 + MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic) throws NoAccessException {
12.135 checkSymbolicClass(refc); // do this before attempting to resolve
12.136 int mods = (isStatic ? Modifier.STATIC : 0);
12.137 return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull());
12.138 }
12.139
12.140 MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic,
12.141 - boolean searchSupers, Class<?> specialCaller) {
12.142 + boolean searchSupers, Class<?> specialCaller) throws NoAccessException {
12.143 checkSymbolicClass(refc); // do this before attempting to resolve
12.144 int mods = (isStatic ? Modifier.STATIC : 0);
12.145 return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), searchSupers, specialCaller);
12.146 }
12.147
12.148 - void checkSymbolicClass(Class<?> refc) {
12.149 + void checkSymbolicClass(Class<?> refc) throws NoAccessException {
12.150 Class<?> caller = lookupClassOrNull();
12.151 if (caller != null && !VerifyAccess.isClassAccessible(refc, caller))
12.152 throw newNoAccessException("symbolic reference class is not public", new MemberName(refc), caller);
12.153 }
12.154
12.155 - void checkMethod(Class<?> refc, MemberName m, boolean wantStatic) {
12.156 + void checkMethod(Class<?> refc, MemberName m, boolean wantStatic) throws NoAccessException {
12.157 String message;
12.158 if (m.isConstructor())
12.159 message = "expected a method, not a constructor";
12.160 @@ -659,7 +677,7 @@
12.161 throw newNoAccessException(message, m, lookupClass());
12.162 }
12.163
12.164 - void checkAccess(Class<?> refc, MemberName m) {
12.165 + void checkAccess(Class<?> refc, MemberName m) throws NoAccessException {
12.166 int allowedModes = this.allowedModes;
12.167 if (allowedModes == TRUSTED) return;
12.168 int mods = m.getModifiers();
12.169 @@ -695,14 +713,14 @@
12.170 return "member is private to package";
12.171 }
12.172
12.173 - void checkSpecialCaller(Class<?> specialCaller) {
12.174 + void checkSpecialCaller(Class<?> specialCaller) throws NoAccessException {
12.175 if (allowedModes == TRUSTED) return;
12.176 if (!VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))
12.177 throw newNoAccessException("no private access for invokespecial",
12.178 new MemberName(specialCaller), lookupClass());
12.179 }
12.180
12.181 - MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) {
12.182 + MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) throws NoAccessException {
12.183 // The accessing class only has the right to use a protected member
12.184 // on itself or a subclass. Enforce that restriction, from JVMS 5.4.4, etc.
12.185 if (!method.isProtected() || method.isStatic()
12.186 @@ -712,7 +730,7 @@
12.187 else
12.188 return restrictReceiver(method, mh, lookupClass());
12.189 }
12.190 - MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) {
12.191 + MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) throws NoAccessException {
12.192 assert(!method.isStatic());
12.193 Class<?> defc = method.getDeclaringClass(); // receiver type of mh is too wide
12.194 if (defc.isInterface() || !defc.isAssignableFrom(caller)) {
12.195 @@ -898,11 +916,16 @@
12.196 * @return a method handle which always invokes the call site's target
12.197 */
12.198 public static
12.199 - MethodHandle dynamicInvoker(CallSite site) {
12.200 + MethodHandle dynamicInvoker(CallSite site) throws NoAccessException {
12.201 MethodHandle getCSTarget = GET_TARGET;
12.202 - if (getCSTarget == null)
12.203 - GET_TARGET = getCSTarget = Lookup.IMPL_LOOKUP.
12.204 - findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
12.205 + if (getCSTarget == null) {
12.206 + try {
12.207 + GET_TARGET = getCSTarget = Lookup.IMPL_LOOKUP.
12.208 + findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
12.209 + } catch (NoAccessException ex) {
12.210 + throw new InternalError();
12.211 + }
12.212 + }
12.213 MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, getCSTarget, site);
12.214 MethodHandle invoker = exactInvoker(site.type());
12.215 return foldArguments(invoker, getTarget);
12.216 @@ -1260,17 +1283,20 @@
12.217 * <p>
12.218 * <b>Example:</b>
12.219 * <p><blockquote><pre>
12.220 - * MethodHandle cat = MethodHandles.lookup().
12.221 - * findVirtual(String.class, "concat", String.class, String.class);
12.222 - * System.out.println(cat.<String>invokeExact("x", "y")); // xy
12.223 + * import static java.dyn.MethodHandles.*;
12.224 + * import static java.dyn.MethodType.*;
12.225 + * ...
12.226 + * MethodHandle cat = lookup().findVirtual(String.class,
12.227 + * "concat", methodType(String.class, String.class));
12.228 + * System.out.println((String) cat.invokeExact("x", "y")); // xy
12.229 * MethodHandle d0 = dropArguments(cat, 0, String.class);
12.230 - * System.out.println(d0.<String>invokeExact("x", "y", "z")); // xy
12.231 + * System.out.println((String) d0.invokeExact("x", "y", "z")); // yz
12.232 * MethodHandle d1 = dropArguments(cat, 1, String.class);
12.233 - * System.out.println(d1.<String>invokeExact("x", "y", "z")); // xz
12.234 + * System.out.println((String) d1.invokeExact("x", "y", "z")); // xz
12.235 * MethodHandle d2 = dropArguments(cat, 2, String.class);
12.236 - * System.out.println(d2.<String>invokeExact("x", "y", "z")); // yz
12.237 - * MethodHandle d12 = dropArguments(cat, 1, String.class, String.class);
12.238 - * System.out.println(d12.<String>invokeExact("w", "x", "y", "z")); // wz
12.239 + * System.out.println((String) d2.invokeExact("x", "y", "z")); // xy
12.240 + * MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
12.241 + * System.out.println((String) d12.invokeExact("x", 12, true, "z")); // xz
12.242 * </pre></blockquote>
12.243 * @param target the method handle to invoke after the argument is dropped
12.244 * @param valueTypes the type(s) of the argument to drop
12.245 @@ -1562,4 +1588,107 @@
12.246 MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) {
12.247 return MethodHandleImpl.throwException(IMPL_TOKEN, MethodType.methodType(returnType, exType));
12.248 }
12.249 +
12.250 + /**
12.251 + * Produce a wrapper instance of the given "SAM" type which redirects its calls to the given method handle.
12.252 + * A SAM type is a type which declares a single abstract method.
12.253 + * Additionally, it must have either no constructor (as an interface)
12.254 + * or have a public or protected constructor of zero arguments (as a class).
12.255 + * <p>
12.256 + * The resulting instance of the required SAM type will respond to
12.257 + * invocation of the SAM type's single abstract method by calling
12.258 + * the given {@code target} on the incoming arguments,
12.259 + * and returning or throwing whatever the {@code target}
12.260 + * returns or throws. The invocation will be as if by
12.261 + * {@code target.invokeExact}.
12.262 + * <p>
12.263 + * The method handle may throw an <em>undeclared exception</em>,
12.264 + * which means any checked exception (or other checked throwable)
12.265 + * not declared by the SAM type's single abstract method.
12.266 + * If this happens, the throwable will be wrapped in an instance
12.267 + * of {@link UndeclaredThrowableException} and thrown in that
12.268 + * wrapped form.
12.269 + * <p>
12.270 + * The wrapper instance is guaranteed to be of a non-public
12.271 + * implementation class C in a package containing no classes
12.272 + * or methods except system-defined classes and methods.
12.273 + * The implementation class C will have no public supertypes
12.274 + * or public methods beyond the following:
12.275 + * <ul>
12.276 + * <li>the SAM type itself and any methods in the SAM type
12.277 + * <li>the supertypes of the SAM type (if any) and their methods
12.278 + * <li>{@link Object} and its methods
12.279 + * <li>{@link MethodHandleProvider} and its methods
12.280 + * </ul>
12.281 + * <p>
12.282 + * No stable mapping is promised between the SAM type and
12.283 + * the implementation class C. Over time, several implementation
12.284 + * classes might be used for the same SAM type.
12.285 + * <p>
12.286 + * This method is not guaranteed to return a distinct
12.287 + * wrapper object for each separate call. If the JVM is able
12.288 + * to prove that a wrapper has already been created for a given
12.289 + * method handle, or for another method handle with the
12.290 + * same behavior, the JVM may return that wrapper in place of
12.291 + * a new wrapper.
12.292 + * @param target the method handle to invoke from the wrapper
12.293 + * @param samType the desired type of the wrapper, a SAM type
12.294 + * @return a correctly-typed wrapper for the given {@code target}
12.295 + * @throws IllegalArgumentException if the {@code target} throws
12.296 + * an undeclared exception
12.297 + */
12.298 + // ISSUE: Should we delegate equals/hashCode to the targets?
12.299 + // Not useful unless there is a stable equals/hashCode behavior
12.300 + // for MethodHandle, and for MethodHandleProvider.asMethodHandle.
12.301 + public static
12.302 + <T> T asInstance(MethodHandle target, Class<T> samType) {
12.303 + // POC implementation only; violates the above contract several ways
12.304 + final Method sam = getSamMethod(samType);
12.305 + if (sam == null)
12.306 + throw new IllegalArgumentException("not a SAM type: "+samType.getName());
12.307 + MethodType samMT = MethodType.methodType(sam.getReturnType(), sam.getParameterTypes());
12.308 + if (!samMT.equals(target.type()))
12.309 + throw new IllegalArgumentException("wrong method type");
12.310 + final MethodHandle mh = target;
12.311 + return samType.cast(Proxy.newProxyInstance(
12.312 + samType.getClassLoader(),
12.313 + new Class[]{ samType, MethodHandleProvider.class },
12.314 + new InvocationHandler() {
12.315 + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
12.316 + if (method.getDeclaringClass() == MethodHandleProvider.class) {
12.317 + return method.invoke(mh, args);
12.318 + }
12.319 + assert method.equals(sam) : method;
12.320 + return mh.invokeVarargs(args);
12.321 + }
12.322 + }));
12.323 + }
12.324 +
12.325 + private static
12.326 + Method getSamMethod(Class<?> samType) {
12.327 + Method sam = null;
12.328 + for (Method m : samType.getMethods()) {
12.329 + int mod = m.getModifiers();
12.330 + if (Modifier.isAbstract(mod)) {
12.331 + if (sam != null)
12.332 + return null; // too many abstract methods
12.333 + sam = m;
12.334 + }
12.335 + }
12.336 + if (!samType.isInterface() && getSamConstructor(samType) == null)
12.337 + return null; // wrong kind of constructor
12.338 + return sam;
12.339 + }
12.340 +
12.341 + private static
12.342 + Constructor getSamConstructor(Class<?> samType) {
12.343 + for (Constructor c : samType.getDeclaredConstructors()) {
12.344 + if (c.getParameterTypes().length == 0) {
12.345 + int mod = c.getModifiers();
12.346 + if (Modifier.isPublic(mod) || Modifier.isProtected(mod))
12.347 + return c;
12.348 + }
12.349 + }
12.350 + return null;
12.351 + }
12.352 }
13.1 --- a/src/share/classes/java/dyn/MethodType.java Tue Nov 09 22:53:18 2010 -0800
13.2 +++ b/src/share/classes/java/dyn/MethodType.java Wed Nov 10 20:40:19 2010 -0800
13.3 @@ -40,24 +40,37 @@
13.4 * returned by a method handle, or the arguments and return type passed
13.5 * and expected by a method handle caller. Method types must be properly
13.6 * matched between a method handle and all its callers,
13.7 - * and the JVM's operations enforce this matching at all times.
13.8 + * and the JVM's operations enforce this matching at, specifically
13.9 + * during calls to {@link MethodHandle#invokeExact}
13.10 + * and {@link MethodHandle#invokeGeneric}, and during execution
13.11 + * of {@code invokedynamic} instructions.
13.12 * <p>
13.13 * The structure is a return type accompanied by any number of parameter types.
13.14 - * The types (primitive, void, and reference) are represented by Class objects.
13.15 + * The types (primitive, {@code void}, and reference) are represented by {@link Class} objects.
13.16 + * (For ease of exposition, we treat {@code void} as if it were a type.
13.17 + * In fact, it denotes the absence of a return type.)
13.18 * <p>
13.19 - * All instances of <code>MethodType</code> are immutable.
13.20 + * All instances of {@code MethodType} are immutable.
13.21 * Two instances are completely interchangeable if they compare equal.
13.22 * Equality depends on pairwise correspondence of the return and parameter types and on nothing else.
13.23 * <p>
13.24 * This type can be created only by factory methods.
13.25 * All factory methods may cache values, though caching is not guaranteed.
13.26 * <p>
13.27 - * Note: Like classes and strings, method types can be represented directly
13.28 - * as constants to be loaded by {@code ldc} bytecodes.
13.29 + * {@code MethodType} objects are sometimes derived from bytecode instructions
13.30 + * such as {@code invokedynamic}, specifically from the type descriptor strings associated
13.31 + * with the instructions in a class file's constant pool.
13.32 + * When this occurs, any classes named in the descriptor strings must be loaded.
13.33 + * (But they need not be initialized.)
13.34 + * This loading may occur at any time before the {@code MethodType} object is first derived.
13.35 + * <p>
13.36 + * Like classes and strings, method types can be represented directly
13.37 + * in a class file's constant pool as constants to be loaded by {@code ldc} bytecodes.
13.38 + * Loading such a constant causes its component classes to be loaded as necessary.
13.39 * @author John Rose, JSR 292 EG
13.40 */
13.41 public final
13.42 -class MethodType {
13.43 +class MethodType implements java.lang.reflect.Type {
13.44 private final Class<?> rtype;
13.45 private final Class<?>[] ptypes;
13.46 private MethodTypeForm form; // erased form, plus cached data about primitives
13.47 @@ -636,11 +649,11 @@
13.48
13.49 /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
13.50 * Find or create an instance of the given method type.
13.51 - * Any class or interface name embedded in the signature string
13.52 + * Any class or interface name embedded in the descriptor string
13.53 * will be resolved by calling {@link ClassLoader#loadClass(java.lang.String)}
13.54 * on the given loader (or if it is null, on the system class loader).
13.55 * <p>
13.56 - * Note that it is possible to build method types which cannot be
13.57 + * Note that it is possible to encounter method types which cannot be
13.58 * constructed by this method, because their component types are
13.59 * not all reachable from a common class loader.
13.60 * <p>
13.61 @@ -662,8 +675,11 @@
13.62 }
13.63
13.64 /**
13.65 - * Create a bytecode signature representation of the type.
13.66 - * Note that this is not a strict inverse of
13.67 + * Create a bytecode descriptor representation of the method type.
13.68 + * <p>
13.69 + * Note that this is not a strict inverse of {@link #fromMethodDescriptorString}.
13.70 + * Two distinct classes which share a common name but have different class loaders
13.71 + * will appear identical when viewed within descriptor strings.
13.72 * <p>
13.73 * This method is included for the benfit of applications that must
13.74 * generate bytecodes that process method handles and invokedynamic.
14.1 --- a/src/share/classes/java/dyn/NoAccessException.java Tue Nov 09 22:53:18 2010 -0800
14.2 +++ b/src/share/classes/java/dyn/NoAccessException.java Wed Nov 10 20:40:19 2010 -0800
14.3 @@ -37,7 +37,7 @@
14.4 * @author John Rose, JSR 292 EG
14.5 * @since 1.7
14.6 */
14.7 -public class NoAccessException extends RuntimeException {
14.8 +public class NoAccessException extends ReflectiveOperationException {
14.9 private static final long serialVersionUID = 292L;
14.10
14.11 /**
15.1 --- a/src/share/classes/java/dyn/package-info.java Tue Nov 09 22:53:18 2010 -0800
15.2 +++ b/src/share/classes/java/dyn/package-info.java Wed Nov 10 20:40:19 2010 -0800
15.3 @@ -40,20 +40,18 @@
15.4 * The JVM links any such call (regardless of signature) to a dynamically
15.5 * typed method handle invocation. In the case of {@code invokeGeneric},
15.6 * argument and return value conversions are applied.
15.7 + * </li>
15.8 *
15.9 - * <li>In source code, the class {@link java.dyn.InvokeDynamic} appears to accept
15.10 + * <li>In source code, the class {@link java.dyn.InvokeDynamic InvokeDynamic} appears to accept
15.11 * any static method invocation, of any name and any signature.
15.12 * But instead of emitting
15.13 * an {@code invokestatic} instruction for such a call, the Java compiler emits
15.14 * an {@code invokedynamic} instruction with the given name and signature.
15.15 - *
15.16 - * <li>When the JVM links an {@code invokedynamic} instruction, it calls the
15.17 - * {@linkplain java.dyn.Linkage#registerBootstrapMethod(Class, MethodHandle) bootstrap method}
15.18 - * of the containing class to obtain a {@linkplain java.dyn.CallSite call site} object through which
15.19 - * the call site will link its target {@linkplain java.dyn.MethodHandle method handle}.
15.20 + * </li>
15.21 *
15.22 * <li>The JVM bytecode format supports immediate constants of
15.23 - * the classes {@link java.dyn.MethodHandle} and {@link java.dyn.MethodType}.
15.24 + * the classes {@link java.dyn.MethodHandle MethodHandle} and {@link java.dyn.MethodType MethodType}.
15.25 + * </li>
15.26 * </ul>
15.27 *
15.28 * <h2><a name="jvm_mods"></a>Corresponding JVM bytecode format changes</h2>
15.29 @@ -65,18 +63,50 @@
15.30 * The first byte is the opcode 186 (hexadecimal {@code BA}).
15.31 * The next two bytes are a constant pool index (in the same format as for the other {@code invoke} instructions).
15.32 * The final two bytes are reserved for future use and required to be zero.
15.33 - * The constant pool reference is to a entry with tag {@code CONSTANT_NameAndType}
15.34 - * (decimal 12). It is thus not a method reference of any sort, but merely
15.35 - * the method name, argument types, and return type of the dynamic call site.
15.36 - * <em>(TBD: The EG is discussing the possibility of a special constant pool entry type,
15.37 - * so that other information may be added, such as a per-instruction bootstrap
15.38 - * method and/or annotations.)</em>
15.39 + * The constant pool reference of an {@code invokedynamic} instruction is to a entry
15.40 + * with tag {@code CONSTANT_InvokeDynamic} (decimal 17). See below for its format.
15.41 + * The entry specifies the bootstrap method (a {@link java.dyn.MethodHandle MethodHandle} constant),
15.42 + * the dynamic invocation name, and the argument types and return type of the call.
15.43 + * <p>
15.44 + * Each instance of an {@code invokedynamic} instruction is called a <em>dynamic call site</em>.
15.45 + * Multiple instances of an {@code invokedynamic} instruction can share a single
15.46 + * {@code CONSTANT_InvokeDynamic} entry.
15.47 + * In any case, distinct call sites always have distinct linkage state.
15.48 + * <p>
15.49 + * Moreover, for the purpose of distinguishing dynamic call sites,
15.50 + * the JVM is allowed (but not required) to make internal copies
15.51 + * of {@code invokedynamic} instructions, each one
15.52 + * constituting a separate dynamic call site with its own linkage state.
15.53 + * Such copying, if it occurs, cannot be observed except indirectly via
15.54 + * execution of bootstrap methods and target methods.
15.55 + * <p>
15.56 + * A dynamic call site is originally in an unlinked state. In this state, there is
15.57 + * no target method for the call site to invoke.
15.58 + * A dynamic call site is linked by means of a bootstrap method,
15.59 + * as <a href="#bsm">described below</a>.
15.60 + * <p>
15.61 + * <em>(Historic Note: Some older JVMs may allow the index of a {@code CONSTANT_NameAndType}
15.62 + * instead of a {@code CONSTANT_InvokeDynamic}. In earlier, obsolete versions of this API, the
15.63 + * bootstrap method was specified dynamically, in a per-class basis, during class initialization.)</em>
15.64 + *
15.65 + * <h3>constant pool entries for {@code invokedynamic} instructions</h3>
15.66 + * If a constant pool entry has the tag {@code CONSTANT_InvokeDynamic} (decimal 17),
15.67 + * it must contain exactly four more bytes.
15.68 + * The first two bytes after the tag must be an index to a {@code CONSTANT_MethodHandle}
15.69 + * entry, and the second two bytes must be an index to a {@code CONSTANT_NameAndType}.
15.70 + * The first index specifies a bootstrap method used by the associated dynamic call sites.
15.71 + * The second index specifies the method name, argument types, and return type of the dynamic call site.
15.72 + * The structure of such an entry is therefore analogous to a {@code CONSTANT_Methodref},
15.73 + * except that the {@code CONSTANT_Class} reference in a {@code CONSTANT_Methodref} entry
15.74 + * is replaced by a bootstrap method reference.
15.75 *
15.76 * <h3>constant pool entries for {@code MethodType}s</h3>
15.77 * If a constant pool entry has the tag {@code CONSTANT_MethodType} (decimal 16),
15.78 - * it must contain exactly two more bytes, which are an index to a {@code CONSTANT_Utf8}
15.79 - * entry which represents a method type signature. The JVM will ensure that on first
15.80 - * execution of an {@code ldc} instruction for this entry, a {@link java.dyn.MethodType}
15.81 + * it must contain exactly two more bytes, which must be an index to a {@code CONSTANT_Utf8}
15.82 + * entry which represents a method type signature.
15.83 + * <p>
15.84 + * The JVM will ensure that on first
15.85 + * execution of an {@code ldc} instruction for this entry, a {@link java.dyn.MethodType MethodType}
15.86 * will be created which represents the signature.
15.87 * Any classes mentioned in the {@code MethodType} will be loaded if necessary,
15.88 * but not initialized.
15.89 @@ -86,12 +116,15 @@
15.90 * <h3>constant pool entries for {@code MethodHandle}s</h3>
15.91 * If a constant pool entry has the tag {@code CONSTANT_MethodHandle} (decimal 15),
15.92 * it must contain exactly three more bytes. The first byte after the tag is a subtag
15.93 - * value in the range 1 through 9, and the last two are an index to a
15.94 + * value which must be in the range 1 through 9, and the last two must be an index to a
15.95 * {@code CONSTANT_Fieldref}, {@code CONSTANT_Methodref}, or
15.96 * {@code CONSTANT_InterfaceMethodref} entry which represents a field or method
15.97 * for which a method handle is to be created.
15.98 + * Furthermore, the subtag value and the type of the constant index value
15.99 + * must agree according to the table below.
15.100 + * <p>
15.101 * The JVM will ensure that on first execution of an {@code ldc} instruction
15.102 - * for this entry, a {@link java.dyn.MethodHandle} will be created which represents
15.103 + * for this entry, a {@link java.dyn.MethodHandle MethodHandle} will be created which represents
15.104 * the field or method reference, according to the specific mode implied by the subtag.
15.105 * <p>
15.106 * As with {@code CONSTANT_Class} and {@code CONSTANT_MethodType} constants,
15.107 @@ -126,6 +159,129 @@
15.108 * Method handles for subtags {@code REF_getStatic}, {@code REF_putStatic}, and {@code REF_invokeStatic}
15.109 * may force class initialization on their first invocation, just like the corresponding bytecodes.
15.110 *
15.111 + * <h2><a name="bsm"></a>Bootstrap Methods</h2>
15.112 + * Before the JVM can execute a dynamic call site (an {@code invokedynamic} instruction),
15.113 + * the call site must first be <em>linked</em>.
15.114 + * Linking is accomplished by calling a <em>bootstrap method</em>
15.115 + * which is given the static information content of the call site,
15.116 + * and which must produce a {@link java.dyn.MethodHandle method handle}
15.117 + * that gives the behavior of the call site.
15.118 + * <p>
15.119 + * Each {@code invokedynamic} instruction statically specifies its own
15.120 + * bootstrap method as a constant pool reference.
15.121 + * The constant pool reference also specifies the call site's name and type signature,
15.122 + * just like {@code invokevirtual} and the other invoke instructions.
15.123 + * <p>
15.124 + * Linking starts with resolving the constant pool entry for the
15.125 + * bootstrap method, and resolving a {@link java.dyn.MethodType MethodType} object for
15.126 + * the type signature of the dynamic call site.
15.127 + * This resolution process may trigger class loading.
15.128 + * It may therefore throw an error if a class fails to load.
15.129 + * This error becomes the abnormal termination of the dynamic
15.130 + * call site execution.
15.131 + * Linkage does not trigger class initialization.
15.132 + * <p>
15.133 + * Next, the bootstrap method call is started, with four values being stacked:
15.134 + * <ul>
15.135 + * <li>a {@code MethodHandle}, the resolved bootstrap method itself </li>
15.136 + * <li>a {@code Class}, the <em>caller class</em> in which dynamic call site occurs </li>
15.137 + * <li>a {@code String}, the method name mentioned in the call site </li>
15.138 + * <li>a {@code MethodType}, the resolved type signature of the call </li>
15.139 + * </ul>
15.140 + * The method handle is then applied to the other values as if by
15.141 + * {@linkplain java.dyn.MethodHandle#invokeGeneric the <code>invokeGeneric</code> method}.
15.142 + * The returned result must be a {@link java.dyn.CallSite CallSite}, a {@link java.dyn.MethodHandle MethodHandle},
15.143 + * or another {@link java.dyn.MethodHandleProvider MethodHandleProvider} value.
15.144 + * The method {@linkplain java.dyn.MethodHandleProvider#asMethodHandle asMethodHandle}
15.145 + * is then called on the returned value. The result of that second
15.146 + * call is the {@code MethodHandle} which becomes the
15.147 + * permanent binding for the dynamic call site.
15.148 + * That method handle's type must be exactly equal to the type
15.149 + * derived from the dynamic call site signature and passed to
15.150 + * the bootstrap method.
15.151 + * <p>
15.152 + * After resolution, the linkage process may fail in a variety of ways.
15.153 + * All failures are reported by an {@link java.dyn.InvokeDynamicBootstrapError InvokeDynamicBootstrapError},
15.154 + * which is thrown as the abnormal termination of the dynamic call
15.155 + * site execution.
15.156 + * The following circumstances will cause this:
15.157 + * <ul>
15.158 + * <li>the bootstrap method invocation completes abnormally </li>
15.159 + * <li>the result from the bootstrap invocation is not a reference to
15.160 + * an object of type {@link java.dyn.MethodHandleProvider MethodHandleProvider} </li>
15.161 + * <li>the call to {@code asMethodHandle} completes abnormally </li>
15.162 + * <li>the call to {@code asMethodHandle} fails to return a reference to
15.163 + * an object of type {@link java.dyn.MethodHandle MethodHandle} </li>
15.164 + * <li>the method handle produced by {@code asMethodHandle} does not have
15.165 + * the expected {@code MethodType} </li>
15.166 + * </ul>
15.167 + * <h3>timing of linkage</h3>
15.168 + * A dynamic call site is linked just before its first execution.
15.169 + * The bootstrap method call implementing the linkage occurs within
15.170 + * a thread that is attempting a first execution.
15.171 + * <p>
15.172 + * If there are several such threads, the JVM picks one thread
15.173 + * and runs the bootstrap method while the others wait for the
15.174 + * invocation to terminate normally or abnormally.
15.175 + * <p>
15.176 + * After a bootstrap method is called and a method handle target
15.177 + * successfully extracted, the JVM attempts to link the instruction
15.178 + * being executed to the target method handle.
15.179 + * This may fail if there has been intervening linkage
15.180 + * or invalidation event for the same instruction.
15.181 + * If such a failure occurs, the dynamic call site must be
15.182 + * re-executed from the beginning, either re-linking it
15.183 + * (if it has been invalidated) or invoking the target
15.184 + * (if it the instruction has been linked by some other means).
15.185 + * <p>
15.186 + * If the instruction is linked successfully, the target method
15.187 + * handle is invoked to complete the instruction execution.
15.188 + * The state of linkage continues until the method containing the
15.189 + * dynamic call site is garbage collected, or the dynamic call site
15.190 + * is invalidated by an explicit request,
15.191 + * such as {@link java.dyn.Linkage#invalidateCallerClass Linkage.invalidateCallerClass}.
15.192 + * <p>
15.193 + * In an application which requires dynamic call sites with individually
15.194 + * mutable behaviors, their bootstrap methods should produce distinct
15.195 + * {@link java.dyn.CallSite CallSite} objects, one for each linkage request.
15.196 + * <p>
15.197 + * If a class containing {@code invokedynamic} instructions
15.198 + * is {@linkplain java.dyn.Linkage#invalidateCallerClass(Class) invalidated},
15.199 + * subsequent execution of those {@code invokedynamic} instructions
15.200 + * will require linking.
15.201 + * It is as if they had never been executed in the first place.
15.202 + * (However, invalidation does not cause constant pool entries to be
15.203 + * resolved a second time.)
15.204 + * <p>
15.205 + * Invalidation events and bootstrap method calls for a particular
15.206 + * dynamic call site are globally ordered relative to each other.
15.207 + * When an invokedynamic instruction is invalidated, if there is
15.208 + * simultaneously a bootstrap method invocation in process
15.209 + * (in the same thread or a different thread), the result
15.210 + * eventually returned must not be used to link the call site.
15.211 + * Put another way, when a call site is invalidated, its
15.212 + * subsequent linkage (if any) must be performed by a bootstrap method
15.213 + * call initiated after the invalidation occurred.
15.214 + * <p>
15.215 + * If several threads simultaneously execute a bootstrap method for a single dynamic
15.216 + * call site, the JVM must choose one target object and installs it visibly to
15.217 + * all threads. Any other bootstrap method calls are allowed to complete, but their
15.218 + * results are ignored, and their dynamic call site invocations proceed with the originally
15.219 + * chosen target object.
15.220 + * <p>
15.221 + * The JVM is free to duplicate dynamic call sites.
15.222 + * This means that, even if a class contains just one {@code invokedynamic}
15.223 + * instruction, its bootstrap method may be executed several times,
15.224 + * once for each duplicate. Thus, bootstrap method code should not
15.225 + * assume an exclusive one-to-one correspondence between particular occurrences
15.226 + * of {@code invokedynamic} bytecodes in class files and linkage events.
15.227 + * <p>
15.228 + * In principle, each individual execution of an {@code invokedynamic}
15.229 + * instruction could be deemed (by a conforming implementation) to be a separate
15.230 + * duplicate, requiring its own execution of the bootstrap method.
15.231 + * However, implementations are expected to perform code duplication
15.232 + * (if at all) in order to improve performance, not make it worse.
15.233 + *
15.234 * @author John Rose, JSR 292 EG
15.235 */
15.236
16.1 --- a/src/share/classes/sun/dyn/BoundMethodHandle.java Tue Nov 09 22:53:18 2010 -0800
16.2 +++ b/src/share/classes/sun/dyn/BoundMethodHandle.java Wed Nov 10 20:40:19 2010 -0800
16.3 @@ -48,8 +48,6 @@
16.4 private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory(IMPL_TOKEN);
16.5
16.6 // Constructors in this class *must* be package scoped or private.
16.7 - // Exception: JavaMethodHandle constructors are protected.
16.8 - // (The link between JMH and BMH is temporary.)
16.9
16.10 /** Bind a direct MH to its receiver (or first ref. argument).
16.11 * The JVM will pre-dispatch the MH if it is not already static.
16.12 @@ -122,55 +120,6 @@
16.13 assert(this instanceof JavaMethodHandle);
16.14 }
16.15
16.16 - /** Initialize the current object as a Java method handle.
16.17 - */
16.18 - protected BoundMethodHandle(String entryPointName, MethodType type, boolean matchArity) {
16.19 - super(Access.TOKEN, null);
16.20 - MethodHandle entryPoint
16.21 - = findJavaMethodHandleEntryPoint(this.getClass(),
16.22 - entryPointName, type, matchArity);
16.23 - MethodHandleImpl.initType(this, entryPoint.type().dropParameterTypes(0, 1));
16.24 - this.argument = this; // kludge; get rid of
16.25 - this.vmargslot = this.type().parameterSlotDepth(0);
16.26 - initTarget(entryPoint, 0);
16.27 - assert(this instanceof JavaMethodHandle);
16.28 - }
16.29 -
16.30 - private static
16.31 - MethodHandle findJavaMethodHandleEntryPoint(Class<?> caller,
16.32 - String name,
16.33 - MethodType type,
16.34 - boolean matchArity) {
16.35 - if (matchArity) type.getClass(); // elicit NPE
16.36 - List<MemberName> methods = IMPL_NAMES.getMethods(caller, true, name, null, caller);
16.37 - MethodType foundType = null;
16.38 - MemberName foundMethod = null;
16.39 - for (MemberName method : methods) {
16.40 - if (method.getDeclaringClass() == MethodHandle.class)
16.41 - continue; // ignore methods inherited from MH class itself
16.42 - MethodType mtype = method.getMethodType();
16.43 - if (type != null && type.parameterCount() != mtype.parameterCount())
16.44 - continue;
16.45 - else if (foundType == null)
16.46 - foundType = mtype;
16.47 - else if (foundType != mtype)
16.48 - throw newIllegalArgumentException("more than one method named "+name+" in "+caller.getName());
16.49 - // discard overrides
16.50 - if (foundMethod == null)
16.51 - foundMethod = method;
16.52 - else if (foundMethod.getDeclaringClass().isAssignableFrom(method.getDeclaringClass()))
16.53 - foundMethod = method;
16.54 - }
16.55 - if (foundMethod == null)
16.56 - throw newIllegalArgumentException("no method named "+name+" in "+caller.getName());
16.57 - MethodHandle entryPoint = MethodHandleImpl.findMethod(IMPL_TOKEN, foundMethod, true, caller);
16.58 - if (type != null) {
16.59 - MethodType epType = type.insertParameterTypes(0, entryPoint.type().parameterType(0));
16.60 - entryPoint = MethodHandles.convertArguments(entryPoint, epType);
16.61 - }
16.62 - return entryPoint;
16.63 - }
16.64 -
16.65 /** Make sure the given {@code argument} can be used as {@code argnum}-th
16.66 * parameter of the given method handle {@code mh}, which must be a reference.
16.67 * <p>
17.1 --- a/src/share/classes/sun/dyn/CallSiteImpl.java Tue Nov 09 22:53:18 2010 -0800
17.2 +++ b/src/share/classes/sun/dyn/CallSiteImpl.java Wed Nov 10 20:40:19 2010 -0800
17.3 @@ -26,6 +26,7 @@
17.4 package sun.dyn;
17.5
17.6 import java.dyn.*;
17.7 +import static sun.dyn.MemberName.uncaughtException;
17.8
17.9 /**
17.10 * Parts of CallSite known to the JVM.
17.11 @@ -49,18 +50,21 @@
17.12 }
17.13 CallSite site;
17.14 try {
17.15 - if (bootstrapMethod.type().parameterCount() == 3)
17.16 - site = bootstrapMethod.<CallSite>invokeExact(caller, name, type);
17.17 - else if (bootstrapMethod.type().parameterCount() == 4)
17.18 - site = bootstrapMethod.<CallSite>invokeExact(caller, name, type,
17.19 - !(info instanceof java.lang.annotation.Annotation[]) ? null
17.20 - : (java.lang.annotation.Annotation[]) info);
17.21 + Object binding;
17.22 + if (false) // switch when invokeGeneric works
17.23 + binding = bootstrapMethod.invokeGeneric(caller, name, type);
17.24 else
17.25 - throw new InternalError("bad BSM: "+bootstrapMethod);
17.26 - if (!(site instanceof CallSite))
17.27 - throw new InvokeDynamicBootstrapError("class bootstrap method failed to create a call site: "+caller);
17.28 - PRIVATE_INITIALIZE_CALL_SITE.<void>invokeExact(site,
17.29 - name, type,
17.30 + binding = bootstrapMethod.invokeVarargs(new Object[]{ caller, name, type });
17.31 + //System.out.println("BSM for "+name+type+" => "+binding);
17.32 + if (binding instanceof CallSite) {
17.33 + site = (CallSite) binding;
17.34 + } else if (binding instanceof MethodHandleProvider) {
17.35 + MethodHandle target = ((MethodHandleProvider) binding).asMethodHandle();
17.36 + site = new ConstantCallSite(target);
17.37 + } else {
17.38 + throw new ClassCastException("bootstrap method failed to produce a MethodHandle or CallSite");
17.39 + }
17.40 + PRIVATE_INITIALIZE_CALL_SITE.<void>invokeExact(site, name, type,
17.41 callerMethod, callerBCI);
17.42 assert(site.getTarget() != null);
17.43 assert(site.getTarget().type().equals(type));
17.44 @@ -77,11 +81,18 @@
17.45
17.46 // This method is private in CallSite because it touches private fields in CallSite.
17.47 // These private fields (vmmethod, vmindex) are specific to the JVM.
17.48 - private static final MethodHandle PRIVATE_INITIALIZE_CALL_SITE =
17.49 + private static final MethodHandle PRIVATE_INITIALIZE_CALL_SITE;
17.50 + static {
17.51 + try {
17.52 + PRIVATE_INITIALIZE_CALL_SITE =
17.53 MethodHandleImpl.IMPL_LOOKUP.findVirtual(CallSite.class, "initializeFromJVM",
17.54 MethodType.methodType(void.class,
17.55 String.class, MethodType.class,
17.56 MemberName.class, int.class));
17.57 + } catch (NoAccessException ex) {
17.58 + throw uncaughtException(ex);
17.59 + }
17.60 + }
17.61
17.62 public static void setCallSiteTarget(Access token, CallSite site, MethodHandle target) {
17.63 Access.check(token);
18.1 --- a/src/share/classes/sun/dyn/FilterGeneric.java Tue Nov 09 22:53:18 2010 -0800
18.2 +++ b/src/share/classes/sun/dyn/FilterGeneric.java Wed Nov 10 20:40:19 2010 -0800
18.3 @@ -25,12 +25,8 @@
18.4
18.5 package sun.dyn;
18.6
18.7 -import java.dyn.JavaMethodHandle;
18.8 -import java.dyn.MethodHandle;
18.9 -import java.dyn.MethodType;
18.10 -import java.dyn.NoAccessException;
18.11 -import java.lang.reflect.Constructor;
18.12 -import java.lang.reflect.InvocationTargetException;
18.13 +import java.dyn.*;
18.14 +import java.lang.reflect.*;
18.15 import static sun.dyn.MemberName.newIllegalArgumentException;
18.16
18.17 /**
18.18 @@ -119,7 +115,7 @@
18.19
18.20 static MethodHandle make(Kind kind, int pos, MethodHandle filter, MethodHandle target) {
18.21 FilterGeneric fgen = of(kind, pos, filter.type(), target.type());
18.22 - return fgen.makeInstance(kind, pos, filter, target);
18.23 + return fgen.makeInstance(kind, pos, filter, target).asMethodHandle();
18.24 }
18.25
18.26 /** Return the adapter information for this target and filter type. */
19.1 --- a/src/share/classes/sun/dyn/FilterOneArgument.java Tue Nov 09 22:53:18 2010 -0800
19.2 +++ b/src/share/classes/sun/dyn/FilterOneArgument.java Wed Nov 10 20:40:19 2010 -0800
19.3 @@ -25,9 +25,8 @@
19.4
19.5 package sun.dyn;
19.6
19.7 -import java.dyn.JavaMethodHandle;
19.8 -import java.dyn.MethodHandle;
19.9 -import java.dyn.MethodType;
19.10 +import java.dyn.*;
19.11 +import static sun.dyn.MemberName.uncaughtException;
19.12
19.13 /**
19.14 * Unary function composition, useful for many small plumbing jobs.
19.15 @@ -51,8 +50,16 @@
19.16 return target.invokeExact(filteredArgument);
19.17 }
19.18
19.19 - private static final MethodHandle INVOKE =
19.20 - MethodHandleImpl.IMPL_LOOKUP.findVirtual(FilterOneArgument.class, "invoke", MethodType.genericMethodType(1));
19.21 + private static final MethodHandle INVOKE;
19.22 + static {
19.23 + try {
19.24 + INVOKE =
19.25 + MethodHandleImpl.IMPL_LOOKUP.findVirtual(FilterOneArgument.class, "invoke",
19.26 + MethodType.genericMethodType(1));
19.27 + } catch (NoAccessException ex) {
19.28 + throw uncaughtException(ex);
19.29 + }
19.30 + }
19.31
19.32 protected FilterOneArgument(MethodHandle filter, MethodHandle target) {
19.33 super(INVOKE);
20.1 --- a/src/share/classes/sun/dyn/FromGeneric.java Tue Nov 09 22:53:18 2010 -0800
20.2 +++ b/src/share/classes/sun/dyn/FromGeneric.java Wed Nov 10 20:40:19 2010 -0800
20.3 @@ -25,15 +25,9 @@
20.4
20.5 package sun.dyn;
20.6
20.7 -import java.dyn.JavaMethodHandle;
20.8 -import java.dyn.MethodHandle;
20.9 -import java.dyn.MethodHandles;
20.10 -import java.dyn.MethodType;
20.11 -import java.dyn.NoAccessException;
20.12 -import java.lang.reflect.Constructor;
20.13 -import java.lang.reflect.InvocationTargetException;
20.14 -import sun.dyn.util.ValueConversions;
20.15 -import sun.dyn.util.Wrapper;
20.16 +import java.dyn.*;
20.17 +import java.lang.reflect.*;
20.18 +import sun.dyn.util.*;
20.19
20.20 /**
20.21 * Adapters which mediate between incoming calls which are generic
21.1 --- a/src/share/classes/sun/dyn/Invokers.java Tue Nov 09 22:53:18 2010 -0800
21.2 +++ b/src/share/classes/sun/dyn/Invokers.java Wed Nov 10 20:40:19 2010 -0800
21.3 @@ -25,10 +25,7 @@
21.4
21.5 package sun.dyn;
21.6
21.7 -import java.dyn.MethodHandle;
21.8 -import java.dyn.MethodHandles;
21.9 -import java.dyn.MethodType;
21.10 -
21.11 +import java.dyn.*;
21.12
21.13 /**
21.14 * Construction and caching of often-used invokers.
21.15 @@ -63,8 +60,11 @@
21.16 public MethodHandle exactInvoker() {
21.17 MethodHandle invoker = exactInvoker;
21.18 if (invoker != null) return invoker;
21.19 - invoker = MethodHandleImpl.IMPL_LOOKUP.findVirtual(MethodHandle.class, "invoke", targetType);
21.20 - if (invoker == null) throw new InternalError("JVM cannot find invoker for "+targetType);
21.21 + try {
21.22 + invoker = MethodHandleImpl.IMPL_LOOKUP.findVirtual(MethodHandle.class, "invoke", targetType);
21.23 + } catch (NoAccessException ex) {
21.24 + throw new InternalError("JVM cannot find invoker for "+targetType);
21.25 + }
21.26 assert(invokerType(targetType) == invoker.type());
21.27 exactInvoker = invoker;
21.28 return invoker;
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/src/share/classes/sun/dyn/JavaMethodHandle.java Wed Nov 10 20:40:19 2010 -0800
22.3 @@ -0,0 +1,172 @@
22.4 +/*
22.5 + * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
22.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
22.7 + *
22.8 + * This code is free software; you can redistribute it and/or modify it
22.9 + * under the terms of the GNU General Public License version 2 only, as
22.10 + * published by the Free Software Foundation. Oracle designates this
22.11 + * particular file as subject to the "Classpath" exception as provided
22.12 + * by Oracle in the LICENSE file that accompanied this code.
22.13 + *
22.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
22.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22.17 + * version 2 for more details (a copy is included in the LICENSE file that
22.18 + * accompanied this code).
22.19 + *
22.20 + * You should have received a copy of the GNU General Public License version
22.21 + * 2 along with this work; if not, write to the Free Software Foundation,
22.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22.23 + *
22.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22.25 + * or visit www.oracle.com if you need additional information or have any
22.26 + * questions.
22.27 + */
22.28 +
22.29 +package sun.dyn;
22.30 +
22.31 +import java.dyn.*;
22.32 +import sun.dyn.Access;
22.33 +
22.34 +/**
22.35 + * A Java method handle is a deprecated proposal for extending
22.36 + * the basic method handle type with additional
22.37 + * programmer defined methods and fields.
22.38 + * Its behavior as a method handle is determined at instance creation time,
22.39 + * by providing the new instance with an "entry point" method handle
22.40 + * to handle calls. This entry point must accept a leading argument
22.41 + * whose type is the Java method handle itself or a supertype, and the
22.42 + * entry point is always called with the Java method handle itself as
22.43 + * the first argument. This is similar to ordinary virtual methods, which also
22.44 + * accept the receiver object {@code this} as an implicit leading argument.
22.45 + * The {@code MethodType} of the Java method handle is the same as that
22.46 + * of the entry point method handle, with the leading parameter type
22.47 + * omitted.
22.48 + * <p>
22.49 + * Here is an example of usage, creating a hybrid object/functional datum:
22.50 + * <p><blockquote><pre>
22.51 + * class Greeter extends JavaMethodHandle {
22.52 + * private String greeting = "hello";
22.53 + * public void setGreeting(String s) { greeting = s; }
22.54 + * public void run() { System.out.println(greeting+", "+greetee); }
22.55 + * private final String greetee;
22.56 + * Greeter(String greetee) {
22.57 + * super(RUN); // alternatively, super("run")
22.58 + * this.greetee = greetee;
22.59 + * }
22.60 + * // the entry point function is computed once:
22.61 + * private static final MethodHandle RUN
22.62 + * = MethodHandles.lookup().findVirtual(Greeter.class, "run",
22.63 + * MethodType.make(void.class));
22.64 + * }
22.65 + * // class Main { public static void main(String... av) { ...
22.66 + * Greeter greeter = new Greeter("world");
22.67 + * greeter.run(); // prints "hello, world"
22.68 + * // Statically typed method handle invocation (most direct):
22.69 + * MethodHandle mh = greeter;
22.70 + * mh.<void>invokeExact(); // also prints "hello, world"
22.71 + * // Dynamically typed method handle invocation:
22.72 + * MethodHandles.invokeExact(greeter); // also prints "hello, world"
22.73 + * greeter.setGreeting("howdy");
22.74 + * mh.invokeExact(); // prints "howdy, world" (object-like mutable behavior)
22.75 + * </pre></blockquote>
22.76 + * <p>
22.77 + * In the example of {@code Greeter}, the method {@code run} provides the entry point.
22.78 + * The entry point need not be a constant value; it may be independently
22.79 + * computed in each call to the constructor. The entry point does not
22.80 + * even need to be a method on the {@code Greeter} class, though
22.81 + * that is the typical case.
22.82 + * <p>
22.83 + * The entry point may also be provided symbolically, in which case the the
22.84 + * {@code JavaMethodHandle} constructor performs the lookup of the entry point.
22.85 + * This makes it possible to use {@code JavaMethodHandle} to create an anonymous
22.86 + * inner class:
22.87 + * <p><blockquote><pre>
22.88 + * // We can also do this with symbolic names and/or inner classes:
22.89 + * MethodHandles.invokeExact(new JavaMethodHandle("yow") {
22.90 + * void yow() { System.out.println("yow, world"); }
22.91 + * });
22.92 + * </pre></blockquote>
22.93 + * <p>
22.94 + * Here is similar lower-level code which works in terms of a bound method handle.
22.95 + * <p><blockquote><pre>
22.96 + * class Greeter {
22.97 + * public void run() { System.out.println("hello, "+greetee); }
22.98 + * private final String greetee;
22.99 + * Greeter(String greetee) { this.greetee = greetee; }
22.100 + * // the entry point function is computed once:
22.101 + * private static final MethodHandle RUN
22.102 + * = MethodHandles.findVirtual(Greeter.class, "run",
22.103 + * MethodType.make(void.class));
22.104 + * }
22.105 + * // class Main { public static void main(String... av) { ...
22.106 + * Greeter greeter = new Greeter("world");
22.107 + * greeter.run(); // prints "hello, world"
22.108 + * MethodHandle mh = MethodHanndles.insertArgument(Greeter.RUN, 0, greeter);
22.109 + * mh.invokeExact(); // also prints "hello, world"
22.110 + * </pre></blockquote>
22.111 + * Note that the method handle must be separately created as a view on the base object.
22.112 + * This increases footprint, complexity, and dynamic indirections.
22.113 + * <p>
22.114 + * Here is a pure functional value expressed most concisely as an anonymous inner class:
22.115 + * <p><blockquote><pre>
22.116 + * // class Main { public static void main(String... av) { ...
22.117 + * final String greetee = "world";
22.118 + * MethodHandle greeter = new JavaMethodHandle("run") {
22.119 + * private void run() { System.out.println("hello, "+greetee); }
22.120 + * }
22.121 + * greeter.invokeExact(); // prints "hello, world"
22.122 + * </pre></blockquote>
22.123 + * <p>
22.124 + * Here is an abstract parameterized lvalue, efficiently expressed as a subtype of MethodHandle,
22.125 + * and instantiated as an anonymous class. The data structure is a handle to 1-D array,
22.126 + * with a specialized index type (long). It is created by inner class, and uses
22.127 + * signature-polymorphic APIs throughout.
22.128 + * <p><blockquote><pre>
22.129 + * abstract class AssignableMethodHandle extends JavaMethodHandle {
22.130 + * private final MethodHandle setter;
22.131 + * public MethodHandle setter() { return setter; }
22.132 + * public AssignableMethodHandle(String get, String set) {
22.133 + * super(get);
22.134 + * MethodType getType = this.type();
22.135 + * MethodType setType = getType.insertParameterType(getType.parameterCount(), getType.returnType()).changeReturnType(void.class);
22.136 + * this.setter = MethodHandles.publicLookup().bind(this, set, setType);
22.137 + * }
22.138 + * }
22.139 + * // class Main { public static void main(String... av) { ...
22.140 + * final Number[] stuff = { 123, 456 };
22.141 + * AssignableMethodHandle stuffPtr = new AssignableMethodHandle("get", "set") {
22.142 + * public Number get(long i) { return stuff[(int)i]; }
22.143 + * public void set(long i, Object x) { stuff[(int)i] = x; }
22.144 + * }
22.145 + * int x = (Integer) stuffPtr.<Number>invokeExact(1L); // 456
22.146 + * stuffPtr.setter().<void>invokeExact(0L, (Number) 789); // replaces 123 with 789
22.147 + * </pre></blockquote>
22.148 + * @see MethodHandle
22.149 + * @deprecated The JSR 292 EG intends to replace {@code JavaMethodHandle} with
22.150 + * an interface-based API for mixing method handle behavior with other classes.
22.151 + * @author John Rose, JSR 292 EG
22.152 + */
22.153 +public abstract class JavaMethodHandle
22.154 + // Note: This is an implementation inheritance hack, and will be removed
22.155 + // with a JVM change which moves the required hidden behavior onto this class.
22.156 + extends sun.dyn.BoundMethodHandle
22.157 +{
22.158 + private static final Access IMPL_TOKEN = Access.getToken();
22.159 +
22.160 + /**
22.161 + * When creating a {@code JavaMethodHandle}, the actual method handle
22.162 + * invocation behavior will be delegated to the specified {@code entryPoint}.
22.163 + * This may be any method handle which can take the newly constructed object
22.164 + * as a leading parameter.
22.165 + * <p>
22.166 + * The method handle type of {@code this} (i.e, the fully constructed object)
22.167 + * will be {@code entryPoint}, minus the leading argument.
22.168 + * The leading argument will be bound to {@code this} on every method
22.169 + * handle invocation.
22.170 + * @param entryPoint the method handle to handle calls
22.171 + */
22.172 + protected JavaMethodHandle(MethodHandle entryPoint) {
22.173 + super(entryPoint);
22.174 + }
22.175 +}
23.1 --- a/src/share/classes/sun/dyn/MemberName.java Tue Nov 09 22:53:18 2010 -0800
23.2 +++ b/src/share/classes/sun/dyn/MemberName.java Wed Nov 10 20:40:19 2010 -0800
23.3 @@ -521,6 +521,11 @@
23.4 if (lookupClass != null) message += ", from " + lookupClass.getName();
23.5 return new NoAccessException(message);
23.6 }
23.7 + public static Error uncaughtException(Exception ex) {
23.8 + Error err = new InternalError("uncaught exception");
23.9 + err.initCause(ex);
23.10 + return err;
23.11 + }
23.12
23.13 /** Actually making a query requires an access check. */
23.14 public static Factory getFactory(Access token) {
23.15 @@ -641,7 +646,7 @@
23.16 * If lookup fails or access is not permitted, a {@linkplain NoAccessException} is thrown.
23.17 * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
23.18 */
23.19 - public MemberName resolveOrFail(MemberName m, boolean searchSupers, Class<?> lookupClass) {
23.20 + public MemberName resolveOrFail(MemberName m, boolean searchSupers, Class<?> lookupClass) throws NoAccessException {
23.21 MemberName result = resolveOrNull(m, searchSupers, lookupClass);
23.22 if (result != null)
23.23 return result;
24.1 --- a/src/share/classes/sun/dyn/MethodHandleImpl.java Tue Nov 09 22:53:18 2010 -0800
24.2 +++ b/src/share/classes/sun/dyn/MethodHandleImpl.java Wed Nov 10 20:40:19 2010 -0800
24.3 @@ -25,11 +25,8 @@
24.4
24.5 package sun.dyn;
24.6
24.7 -import java.dyn.JavaMethodHandle;
24.8 -import java.dyn.MethodHandle;
24.9 -import java.dyn.MethodHandles;
24.10 +import java.dyn.*;
24.11 import java.dyn.MethodHandles.Lookup;
24.12 -import java.dyn.MethodType;
24.13 import java.util.logging.Level;
24.14 import java.util.logging.Logger;
24.15 import sun.dyn.util.VerifyType;
24.16 @@ -46,6 +43,7 @@
24.17 import sun.misc.Unsafe;
24.18 import static sun.dyn.MemberName.newIllegalArgumentException;
24.19 import static sun.dyn.MemberName.newNoAccessException;
24.20 +import static sun.dyn.MemberName.uncaughtException;
24.21
24.22 /**
24.23 * Base class for method handles, containing JVM-specific fields and logic.
24.24 @@ -173,7 +171,7 @@
24.25 */
24.26 public static
24.27 MethodHandle findMethod(Access token, MemberName method,
24.28 - boolean doDispatch, Class<?> lookupClass) {
24.29 + boolean doDispatch, Class<?> lookupClass) throws NoAccessException {
24.30 Access.check(token); // only trusted calls
24.31 MethodType mtype = method.getMethodType();
24.32 if (!method.isStatic()) {
24.33 @@ -320,7 +318,7 @@
24.34 try {
24.35 VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(AllocateObject.class, "invoke_V", MethodType.genericMethodType(0, true));
24.36 } catch (NoAccessException ex) {
24.37 - throw new InternalError("");
24.38 + throw uncaughtException(ex);
24.39 }
24.40 }
24.41 // Corresponding generic constructor types:
24.42 @@ -416,9 +414,7 @@
24.43 f = c.getDeclaredField(field.getName());
24.44 return unsafe.staticFieldBase(f);
24.45 } catch (Exception ee) {
24.46 - Error e = new InternalError();
24.47 - e.initCause(ee);
24.48 - throw e;
24.49 + throw uncaughtException(ee);
24.50 }
24.51 }
24.52
24.53 @@ -473,10 +469,8 @@
24.54 MethodHandle mh;
24.55 try {
24.56 mh = IMPL_LOOKUP.findVirtual(FieldAccessor.class, name, type);
24.57 - } catch (NoAccessException ee) {
24.58 - Error e = new InternalError("name,type="+name+type);
24.59 - e.initCause(ee);
24.60 - throw e;
24.61 + } catch (NoAccessException ex) {
24.62 + throw uncaughtException(ex);
24.63 }
24.64 if (evclass != vclass || (!isStatic && ecclass != cclass)) {
24.65 MethodType strongType = FieldAccessor.ftype(cclass, vclass, isSetter, isStatic);
24.66 @@ -543,10 +537,8 @@
24.67 MethodHandle mh;
24.68 try {
24.69 mh = IMPL_LOOKUP.findStatic(FieldAccessor.class, name, type);
24.70 - } catch (NoAccessException ee) {
24.71 - Error e = new InternalError("name,type="+name+type);
24.72 - e.initCause(ee);
24.73 - throw e;
24.74 + } catch (NoAccessException ex) {
24.75 + throw uncaughtException(ex);
24.76 }
24.77 if (caclass != null) {
24.78 MethodType strongType = FieldAccessor.atype(caclass, isSetter);
24.79 @@ -1031,7 +1023,7 @@
24.80 try {
24.81 VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithTest.class, "invoke_V", MethodType.genericMethodType(0, true));
24.82 } catch (NoAccessException ex) {
24.83 - throw new InternalError("");
24.84 + throw uncaughtException(ex);
24.85 }
24.86 }
24.87 }
24.88 @@ -1167,7 +1159,7 @@
24.89 try {
24.90 VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithCatch.class, "invoke_V", MethodType.genericMethodType(0, true));
24.91 } catch (NoAccessException ex) {
24.92 - throw new InternalError("");
24.93 + throw uncaughtException(ex);
24.94 }
24.95 }
24.96 }
24.97 @@ -1207,9 +1199,16 @@
24.98 return AdapterMethodHandle.makeRetypeRaw(token, type, THROW_EXCEPTION);
24.99 }
24.100
24.101 - static final MethodHandle THROW_EXCEPTION
24.102 + static final MethodHandle THROW_EXCEPTION;
24.103 + static {
24.104 + try {
24.105 + THROW_EXCEPTION
24.106 = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException",
24.107 MethodType.methodType(Empty.class, Throwable.class));
24.108 + } catch (NoAccessException ex) {
24.109 + throw new RuntimeException(ex);
24.110 + }
24.111 + }
24.112 static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
24.113
24.114 public static String getNameString(Access token, MethodHandle target) {
25.1 --- a/src/share/classes/sun/dyn/MethodHandleNatives.java Tue Nov 09 22:53:18 2010 -0800
25.2 +++ b/src/share/classes/sun/dyn/MethodHandleNatives.java Wed Nov 10 20:40:19 2010 -0800
25.3 @@ -25,9 +25,7 @@
25.4
25.5 package sun.dyn;
25.6
25.7 -import java.dyn.CallSite;
25.8 -import java.dyn.MethodHandle;
25.9 -import java.dyn.MethodType;
25.10 +import java.dyn.*;
25.11 import java.dyn.MethodHandles.Lookup;
25.12 import java.lang.reflect.AccessibleObject;
25.13 import java.lang.reflect.Field;
25.14 @@ -324,18 +322,24 @@
25.15 */
25.16 static MethodHandle linkMethodHandleConstant(Class<?> callerClass, int refKind,
25.17 Class<?> defc, String name, Object type) {
25.18 - Lookup lookup = IMPL_LOOKUP.in(callerClass);
25.19 - switch (refKind) {
25.20 - case REF_getField: return lookup.findGetter( defc, name, (Class<?>) type );
25.21 - case REF_getStatic: return lookup.findStaticGetter( defc, name, (Class<?>) type );
25.22 - case REF_putField: return lookup.findSetter( defc, name, (Class<?>) type );
25.23 - case REF_putStatic: return lookup.findStaticSetter( defc, name, (Class<?>) type );
25.24 - case REF_invokeVirtual: return lookup.findVirtual( defc, name, (MethodType) type );
25.25 - case REF_invokeStatic: return lookup.findStatic( defc, name, (MethodType) type );
25.26 - case REF_invokeSpecial: return lookup.findSpecial( defc, name, (MethodType) type, callerClass );
25.27 - case REF_newInvokeSpecial: return lookup.findConstructor( defc, (MethodType) type );
25.28 - case REF_invokeInterface: return lookup.findVirtual( defc, name, (MethodType) type );
25.29 + try {
25.30 + Lookup lookup = IMPL_LOOKUP.in(callerClass);
25.31 + switch (refKind) {
25.32 + case REF_getField: return lookup.findGetter( defc, name, (Class<?>) type );
25.33 + case REF_getStatic: return lookup.findStaticGetter( defc, name, (Class<?>) type );
25.34 + case REF_putField: return lookup.findSetter( defc, name, (Class<?>) type );
25.35 + case REF_putStatic: return lookup.findStaticSetter( defc, name, (Class<?>) type );
25.36 + case REF_invokeVirtual: return lookup.findVirtual( defc, name, (MethodType) type );
25.37 + case REF_invokeStatic: return lookup.findStatic( defc, name, (MethodType) type );
25.38 + case REF_invokeSpecial: return lookup.findSpecial( defc, name, (MethodType) type, callerClass );
25.39 + case REF_newInvokeSpecial: return lookup.findConstructor( defc, (MethodType) type );
25.40 + case REF_invokeInterface: return lookup.findVirtual( defc, name, (MethodType) type );
25.41 + }
25.42 + throw new IllegalArgumentException("bad MethodHandle constant "+name+" : "+type);
25.43 + } catch (NoAccessException ex) {
25.44 + Error err = new IncompatibleClassChangeError();
25.45 + err.initCause(ex);
25.46 + throw err;
25.47 }
25.48 - throw new IllegalArgumentException("bad MethodHandle constant "+name+" : "+type);
25.49 }
25.50 }
26.1 --- a/src/share/classes/sun/dyn/SpreadGeneric.java Tue Nov 09 22:53:18 2010 -0800
26.2 +++ b/src/share/classes/sun/dyn/SpreadGeneric.java Wed Nov 10 20:40:19 2010 -0800
26.3 @@ -25,11 +25,7 @@
26.4
26.5 package sun.dyn;
26.6
26.7 -import java.dyn.JavaMethodHandle;
26.8 -import java.dyn.MethodHandle;
26.9 -import java.dyn.MethodHandles;
26.10 -import java.dyn.MethodType;
26.11 -import java.dyn.NoAccessException;
26.12 +import java.dyn.*;
26.13 import java.lang.reflect.Constructor;
26.14 import java.lang.reflect.InvocationTargetException;
26.15 import java.util.ArrayList;
27.1 --- a/src/share/classes/sun/dyn/ToGeneric.java Tue Nov 09 22:53:18 2010 -0800
27.2 +++ b/src/share/classes/sun/dyn/ToGeneric.java Wed Nov 10 20:40:19 2010 -0800
27.3 @@ -25,11 +25,7 @@
27.4
27.5 package sun.dyn;
27.6
27.7 -import java.dyn.JavaMethodHandle;
27.8 -import java.dyn.MethodHandle;
27.9 -import java.dyn.MethodHandles;
27.10 -import java.dyn.MethodType;
27.11 -import java.dyn.NoAccessException;
27.12 +import java.dyn.*;
27.13 import java.lang.reflect.Constructor;
27.14 import java.lang.reflect.InvocationTargetException;
27.15 import sun.dyn.util.ValueConversions;
28.1 --- a/src/share/classes/sun/dyn/util/ValueConversions.java Tue Nov 09 22:53:18 2010 -0800
28.2 +++ b/src/share/classes/sun/dyn/util/ValueConversions.java Wed Nov 10 20:40:19 2010 -0800
28.3 @@ -34,6 +34,7 @@
28.4 import sun.dyn.Access;
28.5 import sun.dyn.AdapterMethodHandle;
28.6 import sun.dyn.MethodHandleImpl;
28.7 +import static sun.dyn.MemberName.uncaughtException;
28.8
28.9 public class ValueConversions {
28.10 private static final Access IMPL_TOKEN = Access.getToken();
28.11 @@ -148,11 +149,16 @@
28.12 // look up the method
28.13 String name = "unbox" + wrap.simpleName() + (raw ? "Raw" : "");
28.14 MethodType type = unboxType(wrap, raw);
28.15 - if (!exact)
28.16 - // actually, type is wrong; the Java method takes Object
28.17 - mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type.erase());
28.18 - else
28.19 + if (!exact) {
28.20 + try {
28.21 + // actually, type is wrong; the Java method takes Object
28.22 + mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type.erase());
28.23 + } catch (NoAccessException ex) {
28.24 + mh = null;
28.25 + }
28.26 + } else {
28.27 mh = retype(type, unbox(wrap, !exact, raw));
28.28 + }
28.29 if (mh != null) {
28.30 cache.put(wrap, mh);
28.31 return mh;
28.32 @@ -280,10 +286,15 @@
28.33 // look up the method
28.34 String name = "box" + wrap.simpleName() + (raw ? "Raw" : "");
28.35 MethodType type = boxType(wrap, raw);
28.36 - if (exact)
28.37 - mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type);
28.38 - else
28.39 + if (exact) {
28.40 + try {
28.41 + mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type);
28.42 + } catch (NoAccessException ex) {
28.43 + mh = null;
28.44 + }
28.45 + } else {
28.46 mh = retype(type.erase(), box(wrap, !exact, raw));
28.47 + }
28.48 if (mh != null) {
28.49 cache.put(wrap, mh);
28.50 return mh;
28.51 @@ -394,10 +405,15 @@
28.52 // look up the method
28.53 String name = "reboxRaw" + wrap.simpleName();
28.54 MethodType type = reboxType(wrap);
28.55 - if (exact)
28.56 - mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type);
28.57 - else
28.58 + if (exact) {
28.59 + try {
28.60 + mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type);
28.61 + } catch (NoAccessException ex) {
28.62 + mh = null;
28.63 + }
28.64 + } else {
28.65 mh = retype(IDENTITY.type(), rebox(wrap, !exact));
28.66 + }
28.67 if (mh != null) {
28.68 cache.put(wrap, mh);
28.69 return mh;
28.70 @@ -474,7 +490,11 @@
28.71 mh = EMPTY;
28.72 break;
28.73 case INT: case LONG: case FLOAT: case DOUBLE:
28.74 - mh = IMPL_LOOKUP.findStatic(ValueConversions.class, "zero"+wrap.simpleName(), type);
28.75 + try {
28.76 + mh = IMPL_LOOKUP.findStatic(ValueConversions.class, "zero"+wrap.simpleName(), type);
28.77 + } catch (NoAccessException ex) {
28.78 + mh = null;
28.79 + }
28.80 break;
28.81 }
28.82 if (mh != null) {
28.83 @@ -549,8 +569,8 @@
28.84 ZERO_OBJECT = IMPL_LOOKUP.findStatic(ValueConversions.class, "zeroObject", zeroObjectType);
28.85 IGNORE = IMPL_LOOKUP.findStatic(ValueConversions.class, "ignore", ignoreType);
28.86 EMPTY = IMPL_LOOKUP.findStatic(ValueConversions.class, "empty", ignoreType.dropParameterTypes(0, 1));
28.87 - } catch (RuntimeException ex) {
28.88 - throw ex;
28.89 + } catch (Exception ex) {
28.90 + throw uncaughtException(ex);
28.91 }
28.92 }
28.93
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
29.2 +++ b/test/java/dyn/ClassValueTest.java Wed Nov 10 20:40:19 2010 -0800
29.3 @@ -0,0 +1,164 @@
29.4 +/*
29.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
29.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
29.7 + *
29.8 + * This code is free software; you can redistribute it and/or modify it
29.9 + * under the terms of the GNU General Public License version 2 only, as
29.10 + * published by the Free Software Foundation. Oracle designates this
29.11 + * particular file as subject to the "Classpath" exception as provided
29.12 + * by Oracle in the LICENSE file that accompanied this code.
29.13 + *
29.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
29.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
29.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
29.17 + * version 2 for more details (a copy is included in the LICENSE file that
29.18 + * accompanied this code).
29.19 + *
29.20 + * You should have received a copy of the GNU General Public License version
29.21 + * 2 along with this work; if not, write to the Free Software Foundation,
29.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
29.23 + *
29.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
29.25 + * or visit www.oracle.com if you need additional information or have any
29.26 + * questions.
29.27 + */
29.28 +
29.29 +/* @test
29.30 + * @summary tests for class-specific values
29.31 + * @compile ClassValueTest.java
29.32 + * @run junit/othervm test.java.dyn.ClassValueTest
29.33 + */
29.34 +
29.35 +/*
29.36 + Manually:
29.37 + $ $JAVA7X_HOME/bin/javac -d foo -cp $JUNIT4_JAR test/java/dyn/ClassValueTest.java
29.38 + $ $JAVA7X_HOME/bin/java -cp foo:$JUNIT4_JAR org.junit.runner.JUnitCore test.java.dyn.ClassValueTest
29.39 + Output: .testAdd => 1000 : Integer
29.40 + */
29.41 +
29.42 +package test.java.dyn;
29.43 +
29.44 +import java.util.*;
29.45 +
29.46 +import java.dyn.*;
29.47 +
29.48 +import org.junit.*;
29.49 +import static org.junit.Assert.*;
29.50 +
29.51 +/**
29.52 + * @author jrose
29.53 + */
29.54 +public class ClassValueTest {
29.55 + static String nameForCV1(Class<?> type) {
29.56 + return "CV1:" + type.getName();
29.57 + }
29.58 + static int countForCV1;
29.59 + static final ClassValue<String> CV1 = new ClassValue<String>() {
29.60 + protected String computeValue(Class<?> type) {
29.61 + countForCV1++;
29.62 + return nameForCV1(type);
29.63 + }
29.64 + };
29.65 +
29.66 + static final Class[] CLASSES = {
29.67 + String.class,
29.68 + Integer.class,
29.69 + int.class,
29.70 + boolean[].class,
29.71 + char[][].class,
29.72 + ClassValueTest.class
29.73 + };
29.74 +
29.75 + @Test
29.76 + public void testGet() {
29.77 + countForCV1 = 0;
29.78 + for (Class c : CLASSES) {
29.79 + assertEquals(nameForCV1(c), CV1.get(c));
29.80 + }
29.81 + assertEquals(CLASSES.length, countForCV1);
29.82 + for (Class c : CLASSES) {
29.83 + assertEquals(nameForCV1(c), CV1.get(c));
29.84 + }
29.85 + assertEquals(CLASSES.length, countForCV1);
29.86 + }
29.87 +
29.88 + @Test
29.89 + public void testRemove() {
29.90 + for (Class c : CLASSES) {
29.91 + CV1.get(c);
29.92 + }
29.93 + countForCV1 = 0;
29.94 + int REMCOUNT = 3;
29.95 + for (int i = 0; i < REMCOUNT; i++) {
29.96 + CV1.remove(CLASSES[i]);
29.97 + }
29.98 + assertEquals(0, countForCV1); // no change
29.99 + for (Class c : CLASSES) {
29.100 + assertEquals(nameForCV1(c), CV1.get(c));
29.101 + }
29.102 + assertEquals(REMCOUNT, countForCV1);
29.103 + }
29.104 +
29.105 + static String nameForCVN(Class<?> type, int n) {
29.106 + return "CV[" + n + "]" + type.getName();
29.107 + }
29.108 + static int countForCVN;
29.109 + static class CVN extends ClassValue<String> {
29.110 + final int n;
29.111 + CVN(int n) { this.n = n; }
29.112 + protected String computeValue(Class<?> type) {
29.113 + countForCVN++;
29.114 + return nameForCVN(type, n);
29.115 + }
29.116 + };
29.117 +
29.118 + @Test
29.119 + public void testGetMany() {
29.120 + int CVN_COUNT1 = 100, CVN_COUNT2 = 100;
29.121 + CVN cvns[] = new CVN[CVN_COUNT1 * CVN_COUNT2];
29.122 + for (int n = 0; n < cvns.length; n++) {
29.123 + cvns[n] = new CVN(n);
29.124 + }
29.125 + countForCVN = 0;
29.126 + for (int pass = 0; pass <= 2; pass++) {
29.127 + for (int i1 = 0; i1 < CVN_COUNT1; i1++) {
29.128 + eachClass:
29.129 + for (Class c : CLASSES) {
29.130 + for (int i2 = 0; i2 < CVN_COUNT2; i2++) {
29.131 + int n = i1*CVN_COUNT2 + i2;
29.132 + assertEquals(0, countForCVN);
29.133 + assertEquals(nameForCVN(c, n), cvns[n].get(c));
29.134 + cvns[n].get(c); //get it again
29.135 + //System.out.println("getting "+n+":"+cvns[n].get(c));
29.136 + boolean doremove = (((i1 + i2) & 3) == 0);
29.137 + switch (pass) {
29.138 + case 0:
29.139 + assertEquals(1, countForCVN);
29.140 + break;
29.141 + case 1:
29.142 + // remove on middle pass
29.143 + assertEquals(0, countForCVN);
29.144 + if (doremove) {
29.145 + //System.out.println("removing "+n+":"+cvns[n].get(c));
29.146 + cvns[n].remove(c);
29.147 + assertEquals(0, countForCVN);
29.148 + }
29.149 + break;
29.150 + case 2:
29.151 + assertEquals(doremove ? 1 : 0, countForCVN);
29.152 + break;
29.153 + }
29.154 + countForCVN = 0;
29.155 + if (i1 > i2 && i1 < i2+5) continue eachClass; // leave diagonal gap
29.156 + }
29.157 + }
29.158 + }
29.159 + }
29.160 + assertEquals(countForCVN, 0);
29.161 + for (int n = 0; n < cvns.length; n++) {
29.162 + for (Class c : CLASSES) {
29.163 + assertEquals(nameForCVN(c, n), cvns[n].get(c));
29.164 + }
29.165 + }
29.166 + }
29.167 +}
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
30.2 +++ b/test/java/dyn/JavaDocExamples.java Wed Nov 10 20:40:19 2010 -0800
30.3 @@ -0,0 +1,128 @@
30.4 +/*
30.5 + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
30.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
30.7 + *
30.8 + * This code is free software; you can redistribute it and/or modify it
30.9 + * under the terms of the GNU General Public License version 2 only, as
30.10 + * published by the Free Software Foundation. Oracle designates this
30.11 + * particular file as subject to the "Classpath" exception as provided
30.12 + * by Oracle in the LICENSE file that accompanied this code.
30.13 + *
30.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
30.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
30.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
30.17 + * version 2 for more details (a copy is included in the LICENSE file that
30.18 + * accompanied this code).
30.19 + *
30.20 + * You should have received a copy of the GNU General Public License version
30.21 + * 2 along with this work; if not, write to the Free Software Foundation,
30.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
30.23 + *
30.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
30.25 + * or visit www.oracle.com if you need additional information or have any
30.26 + * questions.
30.27 + */
30.28 +
30.29 +/* @test
30.30 + * @summary example code used in javadoc for java.dyn API
30.31 + * @compile -XDallowTransitionalJSR292=no JavaDocExamples.java
30.32 + * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.JavaDocExamples
30.33 + */
30.34 +
30.35 +/*
30.36 +---- To run outside jtreg:
30.37 +$ $JAVA7X_HOME/bin/javac -cp $JUNIT4_JAR -d /tmp/Classes \
30.38 + $DAVINCI/sources/jdk/test/java/dyn/JavaDocExamples.java
30.39 +$ $JAVA7X_HOME/bin/java -cp $JUNIT4_JAR:/tmp/Classes \
30.40 + -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles \
30.41 + -Dtest.java.dyn.JavaDocExamples.verbosity=1 \
30.42 + test.java.dyn.JavaDocExamples
30.43 +----
30.44 +*/
30.45 +
30.46 +package test.java.dyn;
30.47 +
30.48 +import java.dyn.*;
30.49 +import static java.dyn.MethodHandles.*;
30.50 +import static java.dyn.MethodType.*;
30.51 +
30.52 +import java.lang.reflect.*;
30.53 +import java.util.*;
30.54 +
30.55 +import org.junit.*;
30.56 +import static org.junit.Assert.*;
30.57 +import static org.junit.Assume.*;
30.58 +
30.59 +
30.60 +/**
30.61 + * @author jrose
30.62 + */
30.63 +public class JavaDocExamples {
30.64 + /** Wrapper for running the JUnit tests in this module.
30.65 + * Put JUnit on the classpath!
30.66 + */
30.67 + public static void main(String... ignore) {
30.68 + org.junit.runner.JUnitCore.runClasses(JavaDocExamples.class);
30.69 + }
30.70 + // How much output?
30.71 + static int verbosity = Integer.getInteger("test.java.dyn.JavaDocExamples.verbosity", 0);
30.72 +
30.73 +{}
30.74 +static final private Lookup LOOKUP = lookup();
30.75 +// static final private MethodHandle CONCAT_1 = LOOKUP.findVirtual(String.class,
30.76 +// "concat", methodType(String.class, String.class));
30.77 +// static final private MethodHandle HASHCODE_1 = LOOKUP.findVirtual(Object.class,
30.78 +// "hashCode", methodType(int.class));
30.79 +
30.80 +// form required if NoAccessException is intercepted:
30.81 +static final private MethodHandle CONCAT_2, HASHCODE_2;
30.82 +static {
30.83 + try {
30.84 + CONCAT_2 = LOOKUP.findVirtual(String.class,
30.85 + "concat", methodType(String.class, String.class));
30.86 + HASHCODE_2 = LOOKUP.findVirtual(Object.class,
30.87 + "hashCode", methodType(int.class));
30.88 + } catch (NoAccessException ex) {
30.89 + throw new RuntimeException(ex);
30.90 + }
30.91 +}
30.92 +{}
30.93 +
30.94 + @Test public void testFindVirtual() throws Throwable {
30.95 +{}
30.96 +MethodHandle CONCAT_3 = LOOKUP.findVirtual(String.class,
30.97 + "concat", methodType(String.class, String.class));
30.98 +MethodHandle HASHCODE_3 = LOOKUP.findVirtual(Object.class,
30.99 + "hashCode", methodType(int.class));
30.100 +//assertEquals("xy", (String) CONCAT_1.invokeExact("x", "y"));
30.101 +assertEquals("xy", (String) CONCAT_2.<String>invokeExact("x", "y"));
30.102 +assertEquals("xy", (String) CONCAT_3.<String>invokeExact("x", "y"));
30.103 +//assertEquals("xy".hashCode(), (int) HASHCODE_1.<int>invokeExact((Object)"xy"));
30.104 +assertEquals("xy".hashCode(), (int) HASHCODE_2.<int>invokeExact((Object)"xy"));
30.105 +assertEquals("xy".hashCode(), (int) HASHCODE_3.<int>invokeExact((Object)"xy"));
30.106 +{}
30.107 + }
30.108 + @Test public void testDropArguments() throws Throwable {
30.109 + {{
30.110 +{} /// JAVADOC
30.111 +MethodHandle cat = lookup().findVirtual(String.class,
30.112 + "concat", methodType(String.class, String.class));
30.113 +cat = cat.asType(methodType(Object.class, String.class, String.class)); /*(String)*/
30.114 +assertEquals("xy", /*(String)*/ cat.invokeExact("x", "y"));
30.115 +MethodHandle d0 = dropArguments(cat, 0, String.class);
30.116 +assertEquals("yz", /*(String)*/ d0.invokeExact("x", "y", "z"));
30.117 +MethodHandle d1 = dropArguments(cat, 1, String.class);
30.118 +assertEquals("xz", /*(String)*/ d1.invokeExact("x", "y", "z"));
30.119 +MethodHandle d2 = dropArguments(cat, 2, String.class);
30.120 +assertEquals("xy", /*(String)*/ d2.invokeExact("x", "y", "z"));
30.121 +MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
30.122 +assertEquals("xz", /*(String)*/ d12.invokeExact("x", 12, true, "z"));
30.123 + }}
30.124 + }
30.125 +
30.126 + static void assertEquals(Object exp, Object act) {
30.127 + if (verbosity > 0)
30.128 + System.out.println("result: "+act);
30.129 + Assert.assertEquals(exp, act);
30.130 + }
30.131 +}
31.1 --- a/test/java/dyn/MethodHandlesTest.java Tue Nov 09 22:53:18 2010 -0800
31.2 +++ b/test/java/dyn/MethodHandlesTest.java Wed Nov 10 20:40:19 2010 -0800
31.3 @@ -265,6 +265,12 @@
31.4 // wrap = Wrapper.forWrapperType(dst);
31.5 // if (wrap != Wrapper.OBJECT)
31.6 // return wrap.wrap(nextArg++);
31.7 + if (param.isInterface()) {
31.8 + for (Class<?> c : param.getClasses()) {
31.9 + if (param.isAssignableFrom(c) && !c.isInterface())
31.10 + { param = c; break; }
31.11 + }
31.12 + }
31.13 if (param.isInterface() || param.isAssignableFrom(String.class))
31.14 return "#"+nextArg();
31.15 else
31.16 @@ -380,7 +386,7 @@
31.17 }
31.18 public static interface IntExample {
31.19 public void v0();
31.20 - static class Impl implements IntExample {
31.21 + public static class Impl implements IntExample {
31.22 public void v0() { called("Int/v0", this); }
31.23 final String name;
31.24 public Impl() { name = "Impl#"+nextArg(); }
31.25 @@ -449,7 +455,7 @@
31.26 countTest(positive);
31.27 MethodType type = MethodType.methodType(ret, params);
31.28 MethodHandle target = null;
31.29 - RuntimeException noAccess = null;
31.30 + Exception noAccess = null;
31.31 try {
31.32 if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
31.33 target = lookup.findStatic(defc, name, type);
31.34 @@ -513,7 +519,7 @@
31.35 String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo
31.36 MethodType type = MethodType.methodType(ret, params);
31.37 MethodHandle target = null;
31.38 - RuntimeException noAccess = null;
31.39 + Exception noAccess = null;
31.40 try {
31.41 if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
31.42 target = lookup.findVirtual(defc, methodName, type);
31.43 @@ -567,7 +573,7 @@
31.44 countTest(positive);
31.45 MethodType type = MethodType.methodType(ret, params);
31.46 MethodHandle target = null;
31.47 - RuntimeException noAccess = null;
31.48 + Exception noAccess = null;
31.49 try {
31.50 if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
31.51 target = lookup.findSpecial(defc, name, type, specialCaller);
31.52 @@ -623,7 +629,7 @@
31.53 MethodType type = MethodType.methodType(ret, params);
31.54 Object receiver = randomArg(defc);
31.55 MethodHandle target = null;
31.56 - RuntimeException noAccess = null;
31.57 + Exception noAccess = null;
31.58 try {
31.59 if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
31.60 target = lookup.bind(receiver, methodName, type);
31.61 @@ -688,7 +694,7 @@
31.62 MethodType type = MethodType.methodType(ret, params);
31.63 Method rmethod = null;
31.64 MethodHandle target = null;
31.65 - RuntimeException noAccess = null;
31.66 + Exception noAccess = null;
31.67 try {
31.68 rmethod = defc.getDeclaredMethod(name, params);
31.69 } catch (NoSuchMethodException ex) {
31.70 @@ -1088,7 +1094,11 @@
31.71 if (rtype != Object.class)
31.72 pfx = rtype.getSimpleName().substring(0, 1).toLowerCase();
31.73 String name = pfx+"id";
31.74 - return PRIVATE.findStatic(Callee.class, name, type);
31.75 + try {
31.76 + return PRIVATE.findStatic(Callee.class, name, type);
31.77 + } catch (Exception ex) {
31.78 + throw new RuntimeException(ex);
31.79 + }
31.80 }
31.81 }
31.82
31.83 @@ -1327,7 +1337,8 @@
31.84 MethodHandle result = MethodHandles.spreadArguments(target2, newType);
31.85 Object[] returnValue;
31.86 if (pos == 0) {
31.87 - returnValue = (Object[]) result.invokeExact(args);
31.88 + Object rawRetVal = result.invokeExact(args);
31.89 + returnValue = (Object[]) rawRetVal;
31.90 } else {
31.91 Object[] args1 = Arrays.copyOfRange(args, 0, pos+1);
31.92 args1[pos] = Arrays.copyOfRange(args, pos, args.length);
31.93 @@ -1817,8 +1828,13 @@
31.94 testCastFailure("unbox/return", 11000);
31.95 }
31.96
31.97 - static class Surprise extends JavaMethodHandle {
31.98 - Surprise() { super("value"); }
31.99 + static class Surprise implements MethodHandleProvider {
31.100 + public MethodHandle asMethodHandle() {
31.101 + return VALUE.bindTo(this);
31.102 + }
31.103 + public MethodHandle asMethodHandle(MethodType type) {
31.104 + return asMethodHandle().asType(type);
31.105 + }
31.106 Object value(Object x) {
31.107 trace("value", x);
31.108 if (boo != null) return boo;
31.109 @@ -1833,22 +1849,32 @@
31.110 static Object refIdentity(Object x) { trace("ref.x", x); return x; }
31.111 static Integer boxIdentity(Integer x) { trace("box.x", x); return x; }
31.112 static int intIdentity(int x) { trace("int.x", x); return x; }
31.113 - static MethodHandle REF_IDENTITY = PRIVATE.findStatic(
31.114 - Surprise.class, "refIdentity",
31.115 - MethodType.methodType(Object.class, Object.class));
31.116 - static MethodHandle BOX_IDENTITY = PRIVATE.findStatic(
31.117 - Surprise.class, "boxIdentity",
31.118 - MethodType.methodType(Integer.class, Integer.class));
31.119 - static MethodHandle INT_IDENTITY = PRIVATE.findStatic(
31.120 - Surprise.class, "intIdentity",
31.121 - MethodType.methodType(int.class, int.class));
31.122 + static MethodHandle VALUE, REF_IDENTITY, BOX_IDENTITY, INT_IDENTITY;
31.123 + static {
31.124 + try {
31.125 + VALUE = PRIVATE.findVirtual(
31.126 + Surprise.class, "value",
31.127 + MethodType.methodType(Object.class, Object.class));
31.128 + REF_IDENTITY = PRIVATE.findStatic(
31.129 + Surprise.class, "refIdentity",
31.130 + MethodType.methodType(Object.class, Object.class));
31.131 + BOX_IDENTITY = PRIVATE.findStatic(
31.132 + Surprise.class, "boxIdentity",
31.133 + MethodType.methodType(Integer.class, Integer.class));
31.134 + INT_IDENTITY = PRIVATE.findStatic(
31.135 + Surprise.class, "intIdentity",
31.136 + MethodType.methodType(int.class, int.class));
31.137 + } catch (Exception ex) {
31.138 + throw new RuntimeException(ex);
31.139 + }
31.140 + }
31.141 }
31.142
31.143 void testCastFailure(String mode, int okCount) throws Throwable {
31.144 countTest(false);
31.145 if (verbosity > 2) System.out.println("mode="+mode);
31.146 Surprise boo = new Surprise();
31.147 - MethodHandle identity = Surprise.REF_IDENTITY, surprise = boo;
31.148 + MethodHandle identity = Surprise.REF_IDENTITY, surprise0 = boo.asMethodHandle(), surprise = surprise0;
31.149 if (mode.endsWith("/return")) {
31.150 if (mode.equals("unbox/return")) {
31.151 // fail on return to ((Integer)surprise).intValue
31.152 @@ -1874,7 +1900,7 @@
31.153 identity = MethodHandles.filterArguments(callee, identity);
31.154 }
31.155 }
31.156 - assertNotSame(mode, surprise, boo);
31.157 + assertNotSame(mode, surprise, surprise0);
31.158 identity = MethodHandles.convertArguments(identity, MethodType.genericMethodType(1));
31.159 surprise = MethodHandles.convertArguments(surprise, MethodType.genericMethodType(1));
31.160 Object x = 42;
31.161 @@ -1936,6 +1962,107 @@
31.162 mh.invokeVarargs(args);
31.163 assertCalled(name, args);
31.164 }
31.165 +
31.166 + static void runForRunnable() {
31.167 + called("runForRunnable");
31.168 + }
31.169 + private interface Fooable {
31.170 + Object foo(Fooable x, Object y);
31.171 + // this is for randomArg:
31.172 + public class Impl implements Fooable {
31.173 + public Object foo(Fooable x, Object y) {
31.174 + throw new RuntimeException("do not call");
31.175 + }
31.176 + final String name;
31.177 + public Impl() { name = "Fooable#"+nextArg(); }
31.178 + @Override public String toString() { return name; }
31.179 + }
31.180 + }
31.181 + static Object fooForFooable(Fooable x, Object y) {
31.182 + return called("fooForFooable", x, y);
31.183 + }
31.184 + private static class MyCheckedException extends Exception {
31.185 + }
31.186 + private interface WillThrow {
31.187 + void willThrow() throws MyCheckedException;
31.188 + }
31.189 +
31.190 + @Test
31.191 + public void testAsInstance() throws Throwable {
31.192 + if (CAN_SKIP_WORKING) return;
31.193 + Lookup lookup = MethodHandles.lookup();
31.194 + {
31.195 + MethodType mt = MethodType.methodType(void.class);
31.196 + MethodHandle mh = lookup.findStatic(MethodHandlesTest.class, "runForRunnable", mt);
31.197 + Runnable proxy = MethodHandles.asInstance(mh, Runnable.class);
31.198 + proxy.run();
31.199 + assertCalled("runForRunnable");
31.200 + }
31.201 + {
31.202 + MethodType mt = MethodType.methodType(Object.class, Fooable.class, Object.class);
31.203 + MethodHandle mh = lookup.findStatic(MethodHandlesTest.class, "fooForFooable", mt);
31.204 + Fooable proxy = MethodHandles.asInstance(mh, Fooable.class);
31.205 + Object[] args = randomArgs(mt.parameterArray());
31.206 + Object result = proxy.foo((Fooable) args[0], args[1]);
31.207 + assertCalled("fooForFooable", args);
31.208 + assertEquals(result, logEntry("fooForFooable", args));
31.209 + }
31.210 + for (Throwable ex : new Throwable[] { new NullPointerException("ok"),
31.211 + new InternalError("ok"),
31.212 + new Throwable("fail"),
31.213 + new Exception("fail"),
31.214 + new MyCheckedException()
31.215 + }) {
31.216 + MethodHandle mh = MethodHandles.throwException(void.class, Throwable.class);
31.217 + mh = MethodHandles.insertArguments(mh, 0, ex);
31.218 + WillThrow proxy = MethodHandles.asInstance(mh, WillThrow.class);
31.219 + try {
31.220 + proxy.willThrow();
31.221 + System.out.println("Failed to throw: "+ex);
31.222 + assertTrue(false);
31.223 + } catch (Throwable ex1) {
31.224 + if (verbosity > 2) {
31.225 + System.out.println("throw "+ex);
31.226 + System.out.println("catch "+(ex == ex1 ? "UNWRAPPED" : ex1));
31.227 + }
31.228 + if (ex instanceof RuntimeException ||
31.229 + ex instanceof Error) {
31.230 + assertSame("must pass unchecked exception out without wrapping", ex, ex1);
31.231 + } else if (ex instanceof MyCheckedException) {
31.232 + assertSame("must pass declared exception out without wrapping", ex, ex1);
31.233 + } else {
31.234 + assertNotSame("must pass undeclared checked exception with wrapping", ex, ex1);
31.235 + UndeclaredThrowableException utex = (UndeclaredThrowableException) ex1;
31.236 + assertSame(ex, utex.getCause());
31.237 + }
31.238 + }
31.239 + }
31.240 + // Test error checking:
31.241 + MethodHandle genericMH = ValueConversions.varargsArray(0);
31.242 + genericMH = MethodHandles.convertArguments(genericMH, genericMH.type().generic());
31.243 + for (Class<?> sam : new Class[] { Runnable.class,
31.244 + Fooable.class,
31.245 + Iterable.class }) {
31.246 + try {
31.247 + // Must throw, because none of these guys has generic type.
31.248 + MethodHandles.asInstance(genericMH, sam);
31.249 + System.out.println("Failed to throw");
31.250 + assertTrue(false);
31.251 + } catch (IllegalArgumentException ex) {
31.252 + }
31.253 + }
31.254 + for (Class<?> nonSAM : new Class[] { Object.class,
31.255 + String.class,
31.256 + CharSequence.class,
31.257 + Example.class }) {
31.258 + try {
31.259 + MethodHandles.asInstance(ValueConversions.varargsArray(0), nonSAM);
31.260 + System.out.println("Failed to throw");
31.261 + assertTrue(false);
31.262 + } catch (IllegalArgumentException ex) {
31.263 + }
31.264 + }
31.265 + }
31.266 }
31.267 // Local abbreviated copy of sun.dyn.util.ValueConversions
31.268 class ValueConversions {