20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang.invoke;
27
28 import java.lang.reflect.*;
29 import java.util.List;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32
33 import sun.invoke.util.ValueConversions;
34 import sun.invoke.util.VerifyAccess;
35 import sun.invoke.util.Wrapper;
36 import sun.reflect.CallerSensitive;
37 import sun.reflect.Reflection;
38 import sun.reflect.misc.ReflectUtil;
39 import sun.security.util.SecurityConstants;
40 import static java.lang.invoke.MethodHandleStatics.*;
41 import static java.lang.invoke.MethodHandleNatives.Constants.*;
42 import java.util.concurrent.ConcurrentHashMap;
43 import sun.security.util.SecurityConstants;
44
45 /**
46 * This class consists exclusively of static methods that operate on or return
47 * method handles. They fall into several categories:
48 * <ul>
49 * <li>Lookup methods which help create method handles for methods and fields.
50 * <li>Combinator methods, which combine or transform pre-existing method handles into new ones.
51 * <li>Other factory methods to create method handles that emulate other common JVM operations or control flow patterns.
52 * </ul>
53 * <p>
54 * @author John Rose, JSR 292 EG
55 * @since 1.7
56 */
57 public class MethodHandles {
58
59 private MethodHandles() { } // do not instantiate
60
61 private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
62 static { MethodHandleImpl.initStatics(); }
63 // See IMPL_LOOKUP below.
2171 * @return a method handle which inserts an additional argument,
2172 * before calling the original method handle
2173 * @throws NullPointerException if the target or the {@code values} array is null
2174 * @see MethodHandle#bindTo
2175 */
2176 public static
2177 MethodHandle insertArguments(MethodHandle target, int pos, Object... values) {
2178 int insCount = values.length;
2179 MethodType oldType = target.type();
2180 int outargs = oldType.parameterCount();
2181 int inargs = outargs - insCount;
2182 if (inargs < 0)
2183 throw newIllegalArgumentException("too many values to insert");
2184 if (pos < 0 || pos > inargs)
2185 throw newIllegalArgumentException("no argument type to append");
2186 MethodHandle result = target;
2187 for (int i = 0; i < insCount; i++) {
2188 Object value = values[i];
2189 Class<?> ptype = oldType.parameterType(pos+i);
2190 if (ptype.isPrimitive()) {
2191 char btype = 'I';
2192 Wrapper w = Wrapper.forPrimitiveType(ptype);
2193 switch (w) {
2194 case LONG: btype = 'J'; break;
2195 case FLOAT: btype = 'F'; break;
2196 case DOUBLE: btype = 'D'; break;
2197 }
2198 // perform unboxing and/or primitive conversion
2199 value = w.convert(value, ptype);
2200 result = result.bindArgument(pos, btype, value);
2201 continue;
2202 }
2203 value = ptype.cast(value); // throw CCE if needed
2204 if (pos == 0) {
2205 result = result.bindReceiver(value);
2206 } else {
2207 result = result.bindArgument(pos, 'L', value);
2208 }
2209 }
2210 return result;
2211 }
2212
2213 /**
2214 * Produces a method handle which will discard some dummy arguments
2215 * before calling some other specified <i>target</i> method handle.
2216 * The type of the new method handle will be the same as the target's type,
2217 * except it will also include the dummy argument types,
2218 * at some given position.
2219 * <p>
2220 * The {@code pos} argument may range between zero and <i>N</i>,
2221 * where <i>N</i> is the arity of the target.
2222 * If {@code pos} is zero, the dummy arguments will precede
2223 * the target's real arguments; if {@code pos} is <i>N</i>
2224 * they will come after.
2225 * <p>
2226 * <b>Example:</b>
2227 * <blockquote><pre>{@code
|
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang.invoke;
27
28 import java.lang.reflect.*;
29 import java.util.List;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32
33 import sun.invoke.util.ValueConversions;
34 import sun.invoke.util.VerifyAccess;
35 import sun.invoke.util.Wrapper;
36 import sun.reflect.CallerSensitive;
37 import sun.reflect.Reflection;
38 import sun.reflect.misc.ReflectUtil;
39 import sun.security.util.SecurityConstants;
40 import java.lang.invoke.LambdaForm.BasicType;
41 import static java.lang.invoke.LambdaForm.BasicType.*;
42 import static java.lang.invoke.MethodHandleStatics.*;
43 import static java.lang.invoke.MethodHandleNatives.Constants.*;
44 import java.util.concurrent.ConcurrentHashMap;
45
46 /**
47 * This class consists exclusively of static methods that operate on or return
48 * method handles. They fall into several categories:
49 * <ul>
50 * <li>Lookup methods which help create method handles for methods and fields.
51 * <li>Combinator methods, which combine or transform pre-existing method handles into new ones.
52 * <li>Other factory methods to create method handles that emulate other common JVM operations or control flow patterns.
53 * </ul>
54 * <p>
55 * @author John Rose, JSR 292 EG
56 * @since 1.7
57 */
58 public class MethodHandles {
59
60 private MethodHandles() { } // do not instantiate
61
62 private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
63 static { MethodHandleImpl.initStatics(); }
64 // See IMPL_LOOKUP below.
2172 * @return a method handle which inserts an additional argument,
2173 * before calling the original method handle
2174 * @throws NullPointerException if the target or the {@code values} array is null
2175 * @see MethodHandle#bindTo
2176 */
2177 public static
2178 MethodHandle insertArguments(MethodHandle target, int pos, Object... values) {
2179 int insCount = values.length;
2180 MethodType oldType = target.type();
2181 int outargs = oldType.parameterCount();
2182 int inargs = outargs - insCount;
2183 if (inargs < 0)
2184 throw newIllegalArgumentException("too many values to insert");
2185 if (pos < 0 || pos > inargs)
2186 throw newIllegalArgumentException("no argument type to append");
2187 MethodHandle result = target;
2188 for (int i = 0; i < insCount; i++) {
2189 Object value = values[i];
2190 Class<?> ptype = oldType.parameterType(pos+i);
2191 if (ptype.isPrimitive()) {
2192 BasicType btype = I_TYPE;
2193 Wrapper w = Wrapper.forPrimitiveType(ptype);
2194 switch (w) {
2195 case LONG: btype = J_TYPE; break;
2196 case FLOAT: btype = F_TYPE; break;
2197 case DOUBLE: btype = D_TYPE; break;
2198 }
2199 // perform unboxing and/or primitive conversion
2200 value = w.convert(value, ptype);
2201 result = result.bindArgument(pos, btype, value);
2202 continue;
2203 }
2204 value = ptype.cast(value); // throw CCE if needed
2205 if (pos == 0) {
2206 result = result.bindReceiver(value);
2207 } else {
2208 result = result.bindArgument(pos, L_TYPE, value);
2209 }
2210 }
2211 return result;
2212 }
2213
2214 /**
2215 * Produces a method handle which will discard some dummy arguments
2216 * before calling some other specified <i>target</i> method handle.
2217 * The type of the new method handle will be the same as the target's type,
2218 * except it will also include the dummy argument types,
2219 * at some given position.
2220 * <p>
2221 * The {@code pos} argument may range between zero and <i>N</i>,
2222 * where <i>N</i> is the arity of the target.
2223 * If {@code pos} is zero, the dummy arguments will precede
2224 * the target's real arguments; if {@code pos} is <i>N</i>
2225 * they will come after.
2226 * <p>
2227 * <b>Example:</b>
2228 * <blockquote><pre>{@code
|