< prev index next >

src/java.base/share/classes/java/lang/invoke/MethodHandles.java

Print this page

1591          *  @return the lookup modes, which limit the kinds of access performed by this lookup object
1592          *  @see #in
1593          *  @see #dropLookupMode
1594          *
1595          *  @revised 9
1596          */
1597         public int lookupModes() {
1598             return allowedModes & ALL_MODES;
1599         }
1600 
1601         /** Embody the current class (the lookupClass) as a lookup class
1602          * for method handle creation.
1603          * Must be called by from a method in this package,
1604          * which in turn is called by a method not in this package.
1605          */
1606         Lookup(Class<?> lookupClass) {
1607             this(lookupClass, null, FULL_POWER_MODES);
1608         }
1609 
1610         private Lookup(Class<?> lookupClass, Class<?> prevLookupClass, int allowedModes) {

1611             assert prevLookupClass == null || ((allowedModes & MODULE) == 0
1612                     && prevLookupClass.getModule() != lookupClass.getModule());
1613             assert !lookupClass.isArray() && !lookupClass.isPrimitive();
1614             this.lookupClass = lookupClass;
1615             this.prevLookupClass = prevLookupClass;
1616             this.allowedModes = allowedModes;
1617         }
1618 
1619         private static Lookup newLookup(Class<?> lookupClass, Class<?> prevLookupClass, int allowedModes) {
1620             // make sure we haven't accidentally picked up a privileged class:
1621             checkUnprivilegedlookupClass(lookupClass);
1622             return new Lookup(lookupClass, prevLookupClass, allowedModes);
1623         }
1624 
1625         /**
1626          * Creates a lookup on the specified new lookup class.
1627          * The resulting object will report the specified
1628          * class as its own {@link #lookupClass() lookupClass}.
1629          *
1630          * <p>

2562 ...
2563 MethodHandle MH_asList = publicLookup().findStatic(Arrays.class,
2564   "asList", methodType(List.class, Object[].class));
2565 assertEquals("[x, y]", MH_asList.invoke("x", "y").toString());
2566          * }</pre></blockquote>
2567          * @param refc the class from which the method is accessed
2568          * @param name the name of the method
2569          * @param type the type of the method
2570          * @return the desired method handle
2571          * @throws NoSuchMethodException if the method does not exist
2572          * @throws IllegalAccessException if access checking fails,
2573          *                                or if the method is not {@code static},
2574          *                                or if the method's variable arity modifier bit
2575          *                                is set and {@code asVarargsCollector} fails
2576          * @throws    SecurityException if a security manager is present and it
2577          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
2578          * @throws NullPointerException if any argument is null
2579          */
2580         public MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
2581             MemberName method = resolveOrFail(REF_invokeStatic, refc, name, type);






2582             return getDirectMethod(REF_invokeStatic, refc, method, findBoundCallerLookup(method));
2583         }
2584 
2585         /**
2586          * Produces a method handle for a virtual method.
2587          * The type of the method handle will be that of the method,
2588          * with the receiver type (usually {@code refc}) prepended.
2589          * The method and all its argument types must be accessible to the lookup object.
2590          * <p>
2591          * When called, the handle will treat the first argument as a receiver
2592          * and, for non-private methods, dispatch on the receiver's type to determine which method
2593          * implementation to enter.
2594          * For private methods the named method in {@code refc} will be invoked on the receiver.
2595          * (The dispatching action is identical with that performed by an
2596          * {@code invokevirtual} or {@code invokeinterface} instruction.)
2597          * <p>
2598          * The first argument will be of type {@code refc} if the lookup
2599          * class has full privileges to access the member.  Otherwise
2600          * the member must be {@code protected} and the first argument
2601          * will be restricted in type to the lookup class.

2707          * If the returned method handle is invoked, the constructor's class will
2708          * be initialized, if it has not already been initialized.
2709          * <p><b>Example:</b>
2710          * <blockquote><pre>{@code
2711 import static java.lang.invoke.MethodHandles.*;
2712 import static java.lang.invoke.MethodType.*;
2713 ...
2714 MethodHandle MH_newArrayList = publicLookup().findConstructor(
2715   ArrayList.class, methodType(void.class, Collection.class));
2716 Collection orig = Arrays.asList("x", "y");
2717 Collection copy = (ArrayList) MH_newArrayList.invokeExact(orig);
2718 assert(orig != copy);
2719 assertEquals(orig, copy);
2720 // a variable-arity constructor:
2721 MethodHandle MH_newProcessBuilder = publicLookup().findConstructor(
2722   ProcessBuilder.class, methodType(void.class, String[].class));
2723 ProcessBuilder pb = (ProcessBuilder)
2724   MH_newProcessBuilder.invoke("x", "y", "z");
2725 assertEquals("[x, y, z]", pb.command().toString());
2726          * }</pre></blockquote>







2727          * @param refc the class or interface from which the method is accessed
2728          * @param type the type of the method, with the receiver argument omitted, and a void return type
2729          * @return the desired method handle
2730          * @throws NoSuchMethodException if the constructor does not exist
2731          * @throws IllegalAccessException if access checking fails
2732          *                                or if the method's variable arity modifier bit
2733          *                                is set and {@code asVarargsCollector} fails
2734          * @throws    SecurityException if a security manager is present and it
2735          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
2736          * @throws NullPointerException if any argument is null
2737          */
2738         public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
2739             if (refc.isArray()) {
2740                 throw new NoSuchMethodException("no constructor for array class: " + refc.getName());
2741             }



2742             String name = "<init>";
2743             MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type);
2744             return getDirectConstructor(refc, ctor);
2745         }
2746 
2747         /**
2748          * Looks up a class by name from the lookup context defined by this {@code Lookup} object,
2749          * <a href="MethodHandles.Lookup.html#equiv">as if resolved</a> by an {@code ldc} instruction.
2750          * Such a resolution, as specified in JVMS 5.4.3.1 section, attempts to locate and load the class,
2751          * and then determines whether the class is accessible to this lookup object.
2752          * <p>
2753          * The lookup context here is determined by the {@linkplain #lookupClass() lookup class},
2754          * its class loader, and the {@linkplain #lookupModes() lookup modes}.
2755          *
2756          * @param targetName the fully qualified name of the class to be looked up.
2757          * @return the requested class.
2758          * @throws SecurityException if a security manager is present and it
2759          *                           <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
2760          * @throws LinkageError if the linkage fails
2761          * @throws ClassNotFoundException if the class cannot be loaded by the lookup class' loader.

3408          * arguments passed to the method handle.
3409          * <p>
3410          * If the constructor's {@code accessible} flag is not set,
3411          * access checking is performed immediately on behalf of the lookup class.
3412          * <p>
3413          * The returned method handle will have
3414          * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
3415          * the constructor's variable arity modifier bit ({@code 0x0080}) is set.
3416          * <p>
3417          * If the returned method handle is invoked, the constructor's class will
3418          * be initialized, if it has not already been initialized.
3419          * @param c the reflected constructor
3420          * @return a method handle which can invoke the reflected constructor
3421          * @throws IllegalAccessException if access checking fails
3422          *                                or if the method's variable arity modifier bit
3423          *                                is set and {@code asVarargsCollector} fails
3424          * @throws NullPointerException if the argument is null
3425          */
3426         public MethodHandle unreflectConstructor(Constructor<?> c) throws IllegalAccessException {
3427             MemberName ctor = new MemberName(c);
3428             assert(ctor.isConstructor());
3429             @SuppressWarnings("deprecation")
3430             Lookup lookup = c.isAccessible() ? IMPL_LOOKUP : this;
3431             return lookup.getDirectConstructorNoSecurityManager(ctor.getDeclaringClass(), ctor);









3432         }
3433 
3434         /**
3435          * Produces a method handle giving read access to a reflected field.
3436          * The type of the method handle will have a return type of the field's
3437          * value type.
3438          * If the field is {@code static}, the method handle will take no arguments.
3439          * Otherwise, its single argument will be the instance containing
3440          * the field.
3441          * If the {@code Field} object's {@code accessible} flag is not set,
3442          * access checking is performed immediately on behalf of the lookup class.
3443          * <p>
3444          * If the field is static, and
3445          * if the returned method handle is invoked, the field's class will
3446          * be initialized, if it has not already been initialized.
3447          * @param f the reflected field
3448          * @return a method handle which can load values from the reflected field
3449          * @throws IllegalAccessException if access checking fails
3450          * @throws NullPointerException if the argument is null
3451          */

3680         }
3681 
3682         void checkSymbolicClass(Class<?> refc) throws IllegalAccessException {
3683             if (!isClassAccessible(refc)) {
3684                 throw new MemberName(refc).makeAccessException("symbolic reference class is not accessible", this);
3685             }
3686         }
3687 
3688         boolean isClassAccessible(Class<?> refc) {
3689             Objects.requireNonNull(refc);
3690             Class<?> caller = lookupClassOrNull();
3691             Class<?> type = refc;
3692             while (type.isArray()) {
3693                 type = type.getComponentType();
3694             }
3695             return caller == null || VerifyAccess.isClassAccessible(type, caller, prevLookupClass, allowedModes);
3696         }
3697 
3698         /** Check name for an illegal leading "&lt;" character. */
3699         void checkMethodName(byte refKind, String name) throws NoSuchMethodException {
3700             if (name.startsWith("<") && refKind != REF_newInvokeSpecial)
3701                 throw new NoSuchMethodException("illegal method name: "+name);



3702         }
3703 
3704         /**
3705          * Find my trustable caller class if m is a caller sensitive method.
3706          * If this lookup object has original full privilege access, then the caller class is the lookupClass.
3707          * Otherwise, if m is caller-sensitive, throw IllegalAccessException.
3708          */
3709         Lookup findBoundCallerLookup(MemberName m) throws IllegalAccessException {
3710             if (MethodHandleNatives.isCallerSensitive(m) && (lookupModes() & ORIGINAL) == 0) {
3711                 // Only lookups with full privilege access are allowed to resolve caller-sensitive methods
3712                 throw new IllegalAccessException("Attempt to lookup caller-sensitive method using restricted lookup object");
3713             }
3714             return this;
3715         }
3716 
3717         /**
3718          * Returns {@code true} if this lookup has {@code PRIVATE} and {@code MODULE} access.
3719          * @return {@code true} if this lookup has {@code PRIVATE} and {@code MODULE} access.
3720          *
3721          * @deprecated This method was originally designed to test {@code PRIVATE} access

3785 
3786             @SuppressWarnings("removal")
3787             SecurityManager smgr = System.getSecurityManager();
3788             if (smgr == null)  return;
3789 
3790             // Step 1:
3791             boolean fullPrivilegeLookup = hasFullPrivilegeAccess();
3792             if (!fullPrivilegeLookup ||
3793                 !VerifyAccess.classLoaderIsAncestor(lookupClass, refc)) {
3794                 ReflectUtil.checkPackageAccess(refc);
3795             }
3796 
3797             // Step 2a:
3798             if (m.isPublic()) return;
3799             if (!fullPrivilegeLookup) {
3800                 smgr.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
3801             }
3802 
3803             // Step 3:
3804             Class<?> defc = m.getDeclaringClass();
3805             if (!fullPrivilegeLookup && defc != refc) {
3806                 ReflectUtil.checkPackageAccess(defc);
3807             }
3808         }
3809 
3810         void checkMethod(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException {
3811             boolean wantStatic = (refKind == REF_invokeStatic);
3812             String message;
3813             if (m.isConstructor())
3814                 message = "expected a method, not a constructor";
3815             else if (!m.isMethod())
3816                 message = "expected a method";
3817             else if (wantStatic != m.isStatic())
3818                 message = wantStatic ? "expected a static method" : "expected a non-static method";
3819             else
3820                 { checkAccess(refKind, refc, m); return; }
3821             throw m.makeAccessException(message, this);
3822         }
3823 
3824         void checkField(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException {
3825             boolean wantStatic = !MethodHandleNatives.refKindHasReceiver(refKind);
3826             String message;
3827             if (wantStatic != m.isStatic())
3828                 message = wantStatic ? "expected a static field" : "expected a non-static field";
3829             else
3830                 { checkAccess(refKind, refc, m); return; }
3831             throw m.makeAccessException(message, this);
3832         }
3833 

3868                 throw m.makeAccessException("unexpected set of a final field", this);
3869             int requestedModes = fixmods(mods);  // adjust 0 => PACKAGE
3870             if ((requestedModes & allowedModes) != 0) {
3871                 if (VerifyAccess.isMemberAccessible(refc, m.getDeclaringClass(),
3872                                                     mods, lookupClass(), previousLookupClass(), allowedModes))
3873                     return;
3874             } else {
3875                 // Protected members can also be checked as if they were package-private.
3876                 if ((requestedModes & PROTECTED) != 0 && (allowedModes & PACKAGE) != 0
3877                         && VerifyAccess.isSamePackage(m.getDeclaringClass(), lookupClass()))
3878                     return;
3879             }
3880             throw m.makeAccessException(accessFailedMessage(refc, m), this);
3881         }
3882 
3883         String accessFailedMessage(Class<?> refc, MemberName m) {
3884             Class<?> defc = m.getDeclaringClass();
3885             int mods = m.getModifiers();
3886             // check the class first:
3887             boolean classOK = (Modifier.isPublic(defc.getModifiers()) &&
3888                                (defc == refc ||
3889                                 Modifier.isPublic(refc.getModifiers())));
3890             if (!classOK && (allowedModes & PACKAGE) != 0) {
3891                 // ignore previous lookup class to check if default package access
3892                 classOK = (VerifyAccess.isClassAccessible(defc, lookupClass(), null, FULL_POWER_MODES) &&
3893                            (defc == refc ||
3894                             VerifyAccess.isClassAccessible(refc, lookupClass(), null, FULL_POWER_MODES)));
3895             }
3896             if (!classOK)
3897                 return "class is not public";
3898             if (Modifier.isPublic(mods))
3899                 return "access to public member failed";  // (how?, module not readable?)
3900             if (Modifier.isPrivate(mods))
3901                 return "member is private";
3902             if (Modifier.isProtected(mods))
3903                 return "member is protected";
3904             return "member is private to package";
3905         }
3906 
3907         private void checkSpecialCaller(Class<?> specialCaller, Class<?> refc) throws IllegalAccessException {
3908             int allowedModes = this.allowedModes;
3909             if (allowedModes == TRUSTED)  return;
3910             if ((lookupModes() & PRIVATE) == 0
3911                 || (specialCaller != lookupClass()
3912                        // ensure non-abstract methods in superinterfaces can be special-invoked
3913                     && !(refc != null && refc.isInterface() && refc.isAssignableFrom(specialCaller))))

3950             final boolean doRestrict    = false;
3951             final boolean checkSecurity = true;
3952             return getDirectMethodCommon(REF_invokeSpecial, refc, method, checkSecurity, doRestrict, callerLookup);
3953         }
3954         /** Check access and get the requested method, eliding security manager checks. */
3955         private MethodHandle getDirectMethodNoSecurityManager(byte refKind, Class<?> refc, MemberName method, Lookup callerLookup) throws IllegalAccessException {
3956             final boolean doRestrict    = true;
3957             final boolean checkSecurity = false;  // not needed for reflection or for linking CONSTANT_MH constants
3958             return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerLookup);
3959         }
3960         /** Common code for all methods; do not call directly except from immediately above. */
3961         private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
3962                                                    boolean checkSecurity,
3963                                                    boolean doRestrict,
3964                                                    Lookup boundCaller) throws IllegalAccessException {
3965             checkMethod(refKind, refc, method);
3966             // Optionally check with the security manager; this isn't needed for unreflect* calls.
3967             if (checkSecurity)
3968                 checkSecurityManager(refc, method);
3969             assert(!method.isMethodHandleInvoke());
3970 
3971             if (refKind == REF_invokeSpecial &&
3972                 refc != lookupClass() &&
3973                 !refc.isInterface() &&
3974                 refc != lookupClass().getSuperclass() &&
3975                 refc.isAssignableFrom(lookupClass())) {
3976                 assert(!method.getName().equals("<init>"));  // not this code path
3977 
3978                 // Per JVMS 6.5, desc. of invokespecial instruction:
3979                 // If the method is in a superclass of the LC,
3980                 // and if our original search was above LC.super,
3981                 // repeat the search (symbolic lookup) from LC.super
3982                 // and continue with the direct superclass of that class,
3983                 // and so forth, until a match is found or no further superclasses exist.
3984                 // FIXME: MemberName.resolve should handle this instead.
3985                 Class<?> refcAsSuper = lookupClass();
3986                 MemberName m2;
3987                 do {
3988                     refcAsSuper = refcAsSuper.getSuperclass();
3989                     m2 = new MemberName(refcAsSuper,
3990                                         method.getName(),

4094                     throw getField.makeAccessException("caller class must be a subclass below the method", lookupClass());
4095                 }
4096                 refc = lookupClass();
4097             }
4098             return VarHandles.makeFieldHandle(getField, refc, getField.getFieldType(),
4099                                               this.allowedModes == TRUSTED && !getField.isTrustedFinalField());
4100         }
4101         /** Check access and get the requested constructor. */
4102         private MethodHandle getDirectConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException {
4103             final boolean checkSecurity = true;
4104             return getDirectConstructorCommon(refc, ctor, checkSecurity);
4105         }
4106         /** Check access and get the requested constructor, eliding security manager checks. */
4107         private MethodHandle getDirectConstructorNoSecurityManager(Class<?> refc, MemberName ctor) throws IllegalAccessException {
4108             final boolean checkSecurity = false;  // not needed for reflection or for linking CONSTANT_MH constants
4109             return getDirectConstructorCommon(refc, ctor, checkSecurity);
4110         }
4111         /** Common code for all constructors; do not call directly except from immediately above. */
4112         private MethodHandle getDirectConstructorCommon(Class<?> refc, MemberName ctor,
4113                                                   boolean checkSecurity) throws IllegalAccessException {
4114             assert(ctor.isConstructor());
4115             checkAccess(REF_newInvokeSpecial, refc, ctor);
4116             // Optionally check with the security manager; this isn't needed for unreflect* calls.
4117             if (checkSecurity)
4118                 checkSecurityManager(refc, ctor);
4119             assert(!MethodHandleNatives.isCallerSensitive(ctor));  // maybeBindCaller not relevant here
4120             return DirectMethodHandle.make(ctor).setVarargs(ctor);
4121         }
4122 
4123         /** Hook called from the JVM (via MethodHandleNatives) to link MH constants:
4124          */
4125         /*non-public*/
4126         MethodHandle linkMethodHandleConstant(byte refKind, Class<?> defc, String name, Object type)
4127                 throws ReflectiveOperationException {
4128             if (!(type instanceof Class || type instanceof MethodType))
4129                 throw new InternalError("unresolved MemberName");
4130             MemberName member = new MemberName(refKind, defc, name, type);
4131             MethodHandle mh = LOOKASIDE_TABLE.get(member);
4132             if (mh != null) {
4133                 checkSymbolicClass(defc);
4134                 return mh;

4273      * @param arrayClass an array type
4274      * @return a method handle which can load values from the given array type
4275      * @throws NullPointerException if the argument is null
4276      * @throws  IllegalArgumentException if arrayClass is not an array type
4277      * @jvms 6.5 {@code aaload} Instruction
4278      */
4279     public static MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException {
4280         return MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.GET);
4281     }
4282 
4283     /**
4284      * Produces a method handle giving write access to elements of an array,
4285      * as if by the {@code astore} bytecode.
4286      * The type of the method handle will have a void return type.
4287      * Its last argument will be the array's element type.
4288      * The first and second arguments will be the array type and int.
4289      *
4290      * <p> When the returned method handle is invoked,
4291      * the array reference and array index are checked.
4292      * A {@code NullPointerException} will be thrown if the array reference
4293      * is {@code null} and an {@code ArrayIndexOutOfBoundsException} will be


4294      * thrown if the index is negative or if it is greater than or equal to
4295      * the length of the array.
4296      *
4297      * @param arrayClass the class of an array
4298      * @return a method handle which can store values into the array type
4299      * @throws NullPointerException if the argument is null
4300      * @throws IllegalArgumentException if arrayClass is not an array type
4301      * @jvms 6.5 {@code aastore} Instruction
4302      */
4303     public static MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
4304         return MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.SET);
4305     }
4306 
4307     /**
4308      * Produces a VarHandle giving access to elements of an array of type
4309      * {@code arrayClass}.  The VarHandle's variable type is the component type
4310      * of {@code arrayClass} and the list of coordinate types is
4311      * {@code (arrayClass, int)}, where the {@code int} coordinate type
4312      * corresponds to an argument that is an index into an array.
4313      * <p>

5045     }
5046 
5047     /**
5048      * Produces a constant method handle of the requested return type which
5049      * returns the default value for that type every time it is invoked.
5050      * The resulting constant method handle will have no side effects.
5051      * <p>The returned method handle is equivalent to {@code empty(methodType(type))}.
5052      * It is also equivalent to {@code explicitCastArguments(constant(Object.class, null), methodType(type))},
5053      * since {@code explicitCastArguments} converts {@code null} to default values.
5054      * @param type the expected return type of the desired method handle
5055      * @return a constant method handle that takes no arguments
5056      *         and returns the default value of the given type (or void, if the type is void)
5057      * @throws NullPointerException if the argument is null
5058      * @see MethodHandles#constant
5059      * @see MethodHandles#empty
5060      * @see MethodHandles#explicitCastArguments
5061      * @since 9
5062      */
5063     public static MethodHandle zero(Class<?> type) {
5064         Objects.requireNonNull(type);
5065         return type.isPrimitive() ?  zero(Wrapper.forPrimitiveType(type), type) : zero(Wrapper.OBJECT, type);






5066     }
5067 
5068     private static MethodHandle identityOrVoid(Class<?> type) {
5069         return type == void.class ? zero(type) : identity(type);
5070     }
5071 
5072     /**
5073      * Produces a method handle of the requested type which ignores any arguments, does nothing,
5074      * and returns a suitable default depending on the return type.
5075      * That is, it returns a zero primitive value, a {@code null}, or {@code void}.
5076      * <p>The returned method handle is equivalent to
5077      * {@code dropArguments(zero(type.returnType()), 0, type.parameterList())}.
5078      *
5079      * @apiNote Given a predicate and target, a useful "if-then" construct can be produced as
5080      * {@code guardWithTest(pred, target, empty(target.type())}.
5081      * @param type the type of the desired method handle
5082      * @return a constant method handle of the given type, which returns a default value of the given return type
5083      * @throws NullPointerException if the argument is null
5084      * @see MethodHandles#zero
5085      * @see MethodHandles#constant
5086      * @since 9
5087      */
5088     public static  MethodHandle empty(MethodType type) {
5089         Objects.requireNonNull(type);
5090         return dropArguments(zero(type.returnType()), 0, type.parameterList());
5091     }
5092 
5093     private static final MethodHandle[] IDENTITY_MHS = new MethodHandle[Wrapper.COUNT];
5094     private static MethodHandle makeIdentity(Class<?> ptype) {
5095         MethodType mtype = methodType(ptype, ptype);
5096         LambdaForm lform = LambdaForm.identityForm(BasicType.basicType(ptype));
5097         return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.IDENTITY);
5098     }
5099 
5100     private static MethodHandle zero(Wrapper btw, Class<?> rtype) {
5101         int pos = btw.ordinal();
5102         MethodHandle zero = ZERO_MHS[pos];
5103         if (zero == null) {
5104             zero = setCachedMethodHandle(ZERO_MHS, pos, makeZero(btw.primitiveType()));
5105         }
5106         if (zero.type().returnType() == rtype)
5107             return zero;
5108         assert(btw == Wrapper.OBJECT);
5109         return makeZero(rtype);
5110     }
5111     private static final MethodHandle[] ZERO_MHS = new MethodHandle[Wrapper.COUNT];
5112     private static MethodHandle makeZero(Class<?> rtype) {
5113         MethodType mtype = methodType(rtype);
5114         LambdaForm lform = LambdaForm.zeroForm(BasicType.basicType(rtype));
5115         return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.ZERO);

1591          *  @return the lookup modes, which limit the kinds of access performed by this lookup object
1592          *  @see #in
1593          *  @see #dropLookupMode
1594          *
1595          *  @revised 9
1596          */
1597         public int lookupModes() {
1598             return allowedModes & ALL_MODES;
1599         }
1600 
1601         /** Embody the current class (the lookupClass) as a lookup class
1602          * for method handle creation.
1603          * Must be called by from a method in this package,
1604          * which in turn is called by a method not in this package.
1605          */
1606         Lookup(Class<?> lookupClass) {
1607             this(lookupClass, null, FULL_POWER_MODES);
1608         }
1609 
1610         private Lookup(Class<?> lookupClass, Class<?> prevLookupClass, int allowedModes) {
1611             assert lookupClass.isPrimaryType();
1612             assert prevLookupClass == null || ((allowedModes & MODULE) == 0
1613                     && prevLookupClass.getModule() != lookupClass.getModule());
1614             assert !lookupClass.isArray() && !lookupClass.isPrimitive();
1615             this.lookupClass = lookupClass;
1616             this.prevLookupClass = prevLookupClass;
1617             this.allowedModes = allowedModes;
1618         }
1619 
1620         private static Lookup newLookup(Class<?> lookupClass, Class<?> prevLookupClass, int allowedModes) {
1621             // make sure we haven't accidentally picked up a privileged class:
1622             checkUnprivilegedlookupClass(lookupClass);
1623             return new Lookup(lookupClass, prevLookupClass, allowedModes);
1624         }
1625 
1626         /**
1627          * Creates a lookup on the specified new lookup class.
1628          * The resulting object will report the specified
1629          * class as its own {@link #lookupClass() lookupClass}.
1630          *
1631          * <p>

2563 ...
2564 MethodHandle MH_asList = publicLookup().findStatic(Arrays.class,
2565   "asList", methodType(List.class, Object[].class));
2566 assertEquals("[x, y]", MH_asList.invoke("x", "y").toString());
2567          * }</pre></blockquote>
2568          * @param refc the class from which the method is accessed
2569          * @param name the name of the method
2570          * @param type the type of the method
2571          * @return the desired method handle
2572          * @throws NoSuchMethodException if the method does not exist
2573          * @throws IllegalAccessException if access checking fails,
2574          *                                or if the method is not {@code static},
2575          *                                or if the method's variable arity modifier bit
2576          *                                is set and {@code asVarargsCollector} fails
2577          * @throws    SecurityException if a security manager is present and it
2578          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
2579          * @throws NullPointerException if any argument is null
2580          */
2581         public MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
2582             MemberName method = resolveOrFail(REF_invokeStatic, refc, name, type);
2583             // resolveOrFail could return a non-static <init> method if present
2584             // detect and throw NSME before producing a MethodHandle
2585             if (!method.isStatic() && name.equals("<init>")) {
2586                 throw new NoSuchMethodException("illegal method name: " + name);
2587             }
2588 
2589             return getDirectMethod(REF_invokeStatic, refc, method, findBoundCallerLookup(method));
2590         }
2591 
2592         /**
2593          * Produces a method handle for a virtual method.
2594          * The type of the method handle will be that of the method,
2595          * with the receiver type (usually {@code refc}) prepended.
2596          * The method and all its argument types must be accessible to the lookup object.
2597          * <p>
2598          * When called, the handle will treat the first argument as a receiver
2599          * and, for non-private methods, dispatch on the receiver's type to determine which method
2600          * implementation to enter.
2601          * For private methods the named method in {@code refc} will be invoked on the receiver.
2602          * (The dispatching action is identical with that performed by an
2603          * {@code invokevirtual} or {@code invokeinterface} instruction.)
2604          * <p>
2605          * The first argument will be of type {@code refc} if the lookup
2606          * class has full privileges to access the member.  Otherwise
2607          * the member must be {@code protected} and the first argument
2608          * will be restricted in type to the lookup class.

2714          * If the returned method handle is invoked, the constructor's class will
2715          * be initialized, if it has not already been initialized.
2716          * <p><b>Example:</b>
2717          * <blockquote><pre>{@code
2718 import static java.lang.invoke.MethodHandles.*;
2719 import static java.lang.invoke.MethodType.*;
2720 ...
2721 MethodHandle MH_newArrayList = publicLookup().findConstructor(
2722   ArrayList.class, methodType(void.class, Collection.class));
2723 Collection orig = Arrays.asList("x", "y");
2724 Collection copy = (ArrayList) MH_newArrayList.invokeExact(orig);
2725 assert(orig != copy);
2726 assertEquals(orig, copy);
2727 // a variable-arity constructor:
2728 MethodHandle MH_newProcessBuilder = publicLookup().findConstructor(
2729   ProcessBuilder.class, methodType(void.class, String[].class));
2730 ProcessBuilder pb = (ProcessBuilder)
2731   MH_newProcessBuilder.invoke("x", "y", "z");
2732 assertEquals("[x, y, z]", pb.command().toString());
2733          * }</pre></blockquote>
2734          *
2735          * @apiNote
2736          * This method does not find a static {@code <init>} factory method as it is invoked
2737          * via {@code invokestatic} bytecode as opposed to {@code invokespecial} for an
2738          * object constructor.  To look up static {@code <init>} factory method, use
2739          * the {@link #findStatic(Class, String, MethodType) findStatic} method.
2740          *
2741          * @param refc the class or interface from which the method is accessed
2742          * @param type the type of the method, with the receiver argument omitted, and a void return type
2743          * @return the desired method handle
2744          * @throws NoSuchMethodException if the constructor does not exist
2745          * @throws IllegalAccessException if access checking fails
2746          *                                or if the method's variable arity modifier bit
2747          *                                is set and {@code asVarargsCollector} fails
2748          * @throws    SecurityException if a security manager is present and it
2749          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
2750          * @throws NullPointerException if any argument is null
2751          */
2752         public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
2753             if (refc.isArray()) {
2754                 throw new NoSuchMethodException("no constructor for array class: " + refc.getName());
2755             }
2756             if (type.returnType() != void.class) {
2757                 throw new NoSuchMethodException("Constructors must have void return type: " + refc.getName());
2758             }
2759             String name = "<init>";
2760             MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type);
2761             return getDirectConstructor(refc, ctor);
2762         }
2763 
2764         /**
2765          * Looks up a class by name from the lookup context defined by this {@code Lookup} object,
2766          * <a href="MethodHandles.Lookup.html#equiv">as if resolved</a> by an {@code ldc} instruction.
2767          * Such a resolution, as specified in JVMS 5.4.3.1 section, attempts to locate and load the class,
2768          * and then determines whether the class is accessible to this lookup object.
2769          * <p>
2770          * The lookup context here is determined by the {@linkplain #lookupClass() lookup class},
2771          * its class loader, and the {@linkplain #lookupModes() lookup modes}.
2772          *
2773          * @param targetName the fully qualified name of the class to be looked up.
2774          * @return the requested class.
2775          * @throws SecurityException if a security manager is present and it
2776          *                           <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
2777          * @throws LinkageError if the linkage fails
2778          * @throws ClassNotFoundException if the class cannot be loaded by the lookup class' loader.

3425          * arguments passed to the method handle.
3426          * <p>
3427          * If the constructor's {@code accessible} flag is not set,
3428          * access checking is performed immediately on behalf of the lookup class.
3429          * <p>
3430          * The returned method handle will have
3431          * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
3432          * the constructor's variable arity modifier bit ({@code 0x0080}) is set.
3433          * <p>
3434          * If the returned method handle is invoked, the constructor's class will
3435          * be initialized, if it has not already been initialized.
3436          * @param c the reflected constructor
3437          * @return a method handle which can invoke the reflected constructor
3438          * @throws IllegalAccessException if access checking fails
3439          *                                or if the method's variable arity modifier bit
3440          *                                is set and {@code asVarargsCollector} fails
3441          * @throws NullPointerException if the argument is null
3442          */
3443         public MethodHandle unreflectConstructor(Constructor<?> c) throws IllegalAccessException {
3444             MemberName ctor = new MemberName(c);
3445             assert(ctor.isObjectConstructorOrStaticInitMethod());
3446             @SuppressWarnings("deprecation")
3447             Lookup lookup = c.isAccessible() ? IMPL_LOOKUP : this;
3448             Class<?> defc = c.getDeclaringClass();
3449             if (ctor.isObjectConstructor()) {
3450                 assert(ctor.getReturnType() == void.class);
3451                 return lookup.getDirectConstructorNoSecurityManager(defc, ctor);
3452             } else {
3453                 // static init factory is a static method
3454                 assert(ctor.isMethod() && ctor.getReturnType() == defc && ctor.getReferenceKind() == REF_invokeStatic) : ctor.toString();
3455                 assert(!MethodHandleNatives.isCallerSensitive(ctor));  // must not be caller-sensitive
3456                 return lookup.getDirectMethodNoSecurityManager(ctor.getReferenceKind(), defc, ctor, lookup);
3457             }
3458         }
3459 
3460         /**
3461          * Produces a method handle giving read access to a reflected field.
3462          * The type of the method handle will have a return type of the field's
3463          * value type.
3464          * If the field is {@code static}, the method handle will take no arguments.
3465          * Otherwise, its single argument will be the instance containing
3466          * the field.
3467          * If the {@code Field} object's {@code accessible} flag is not set,
3468          * access checking is performed immediately on behalf of the lookup class.
3469          * <p>
3470          * If the field is static, and
3471          * if the returned method handle is invoked, the field's class will
3472          * be initialized, if it has not already been initialized.
3473          * @param f the reflected field
3474          * @return a method handle which can load values from the reflected field
3475          * @throws IllegalAccessException if access checking fails
3476          * @throws NullPointerException if the argument is null
3477          */

3706         }
3707 
3708         void checkSymbolicClass(Class<?> refc) throws IllegalAccessException {
3709             if (!isClassAccessible(refc)) {
3710                 throw new MemberName(refc).makeAccessException("symbolic reference class is not accessible", this);
3711             }
3712         }
3713 
3714         boolean isClassAccessible(Class<?> refc) {
3715             Objects.requireNonNull(refc);
3716             Class<?> caller = lookupClassOrNull();
3717             Class<?> type = refc;
3718             while (type.isArray()) {
3719                 type = type.getComponentType();
3720             }
3721             return caller == null || VerifyAccess.isClassAccessible(type, caller, prevLookupClass, allowedModes);
3722         }
3723 
3724         /** Check name for an illegal leading "&lt;" character. */
3725         void checkMethodName(byte refKind, String name) throws NoSuchMethodException {
3726             // "<init>" can only be invoked via invokespecial or it's a static init factory
3727             if (name.startsWith("<") && refKind != REF_newInvokeSpecial &&
3728                     !(refKind == REF_invokeStatic && name.equals("<init>"))) {
3729                     throw new NoSuchMethodException("illegal method name: " + name);
3730             }
3731         }
3732 
3733         /**
3734          * Find my trustable caller class if m is a caller sensitive method.
3735          * If this lookup object has original full privilege access, then the caller class is the lookupClass.
3736          * Otherwise, if m is caller-sensitive, throw IllegalAccessException.
3737          */
3738         Lookup findBoundCallerLookup(MemberName m) throws IllegalAccessException {
3739             if (MethodHandleNatives.isCallerSensitive(m) && (lookupModes() & ORIGINAL) == 0) {
3740                 // Only lookups with full privilege access are allowed to resolve caller-sensitive methods
3741                 throw new IllegalAccessException("Attempt to lookup caller-sensitive method using restricted lookup object");
3742             }
3743             return this;
3744         }
3745 
3746         /**
3747          * Returns {@code true} if this lookup has {@code PRIVATE} and {@code MODULE} access.
3748          * @return {@code true} if this lookup has {@code PRIVATE} and {@code MODULE} access.
3749          *
3750          * @deprecated This method was originally designed to test {@code PRIVATE} access

3814 
3815             @SuppressWarnings("removal")
3816             SecurityManager smgr = System.getSecurityManager();
3817             if (smgr == null)  return;
3818 
3819             // Step 1:
3820             boolean fullPrivilegeLookup = hasFullPrivilegeAccess();
3821             if (!fullPrivilegeLookup ||
3822                 !VerifyAccess.classLoaderIsAncestor(lookupClass, refc)) {
3823                 ReflectUtil.checkPackageAccess(refc);
3824             }
3825 
3826             // Step 2a:
3827             if (m.isPublic()) return;
3828             if (!fullPrivilegeLookup) {
3829                 smgr.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
3830             }
3831 
3832             // Step 3:
3833             Class<?> defc = m.getDeclaringClass();
3834             if (!fullPrivilegeLookup && defc.asPrimaryType() != refc.asPrimaryType()) {
3835                 ReflectUtil.checkPackageAccess(defc);
3836             }
3837         }
3838 
3839         void checkMethod(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException {
3840             boolean wantStatic = (refKind == REF_invokeStatic);
3841             String message;
3842             if (m.isObjectConstructor())
3843                 message = "expected a method, not a constructor";
3844             else if (!m.isMethod())
3845                 message = "expected a method";
3846             else if (wantStatic != m.isStatic())
3847                 message = wantStatic ? "expected a static method" : "expected a non-static method";
3848             else
3849                 { checkAccess(refKind, refc, m); return; }
3850             throw m.makeAccessException(message, this);
3851         }
3852 
3853         void checkField(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException {
3854             boolean wantStatic = !MethodHandleNatives.refKindHasReceiver(refKind);
3855             String message;
3856             if (wantStatic != m.isStatic())
3857                 message = wantStatic ? "expected a static field" : "expected a non-static field";
3858             else
3859                 { checkAccess(refKind, refc, m); return; }
3860             throw m.makeAccessException(message, this);
3861         }
3862 

3897                 throw m.makeAccessException("unexpected set of a final field", this);
3898             int requestedModes = fixmods(mods);  // adjust 0 => PACKAGE
3899             if ((requestedModes & allowedModes) != 0) {
3900                 if (VerifyAccess.isMemberAccessible(refc, m.getDeclaringClass(),
3901                                                     mods, lookupClass(), previousLookupClass(), allowedModes))
3902                     return;
3903             } else {
3904                 // Protected members can also be checked as if they were package-private.
3905                 if ((requestedModes & PROTECTED) != 0 && (allowedModes & PACKAGE) != 0
3906                         && VerifyAccess.isSamePackage(m.getDeclaringClass(), lookupClass()))
3907                     return;
3908             }
3909             throw m.makeAccessException(accessFailedMessage(refc, m), this);
3910         }
3911 
3912         String accessFailedMessage(Class<?> refc, MemberName m) {
3913             Class<?> defc = m.getDeclaringClass();
3914             int mods = m.getModifiers();
3915             // check the class first:
3916             boolean classOK = (Modifier.isPublic(defc.getModifiers()) &&
3917                                (defc.asPrimaryType() == refc.asPrimaryType() ||
3918                                 Modifier.isPublic(refc.getModifiers())));
3919             if (!classOK && (allowedModes & PACKAGE) != 0) {
3920                 // ignore previous lookup class to check if default package access
3921                 classOK = (VerifyAccess.isClassAccessible(defc, lookupClass(), null, FULL_POWER_MODES) &&
3922                            (defc.asPrimaryType() == refc.asPrimaryType() ||
3923                             VerifyAccess.isClassAccessible(refc, lookupClass(), null, FULL_POWER_MODES)));
3924             }
3925             if (!classOK)
3926                 return "class is not public";
3927             if (Modifier.isPublic(mods))
3928                 return "access to public member failed";  // (how?, module not readable?)
3929             if (Modifier.isPrivate(mods))
3930                 return "member is private";
3931             if (Modifier.isProtected(mods))
3932                 return "member is protected";
3933             return "member is private to package";
3934         }
3935 
3936         private void checkSpecialCaller(Class<?> specialCaller, Class<?> refc) throws IllegalAccessException {
3937             int allowedModes = this.allowedModes;
3938             if (allowedModes == TRUSTED)  return;
3939             if ((lookupModes() & PRIVATE) == 0
3940                 || (specialCaller != lookupClass()
3941                        // ensure non-abstract methods in superinterfaces can be special-invoked
3942                     && !(refc != null && refc.isInterface() && refc.isAssignableFrom(specialCaller))))

3979             final boolean doRestrict    = false;
3980             final boolean checkSecurity = true;
3981             return getDirectMethodCommon(REF_invokeSpecial, refc, method, checkSecurity, doRestrict, callerLookup);
3982         }
3983         /** Check access and get the requested method, eliding security manager checks. */
3984         private MethodHandle getDirectMethodNoSecurityManager(byte refKind, Class<?> refc, MemberName method, Lookup callerLookup) throws IllegalAccessException {
3985             final boolean doRestrict    = true;
3986             final boolean checkSecurity = false;  // not needed for reflection or for linking CONSTANT_MH constants
3987             return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerLookup);
3988         }
3989         /** Common code for all methods; do not call directly except from immediately above. */
3990         private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
3991                                                    boolean checkSecurity,
3992                                                    boolean doRestrict,
3993                                                    Lookup boundCaller) throws IllegalAccessException {
3994             checkMethod(refKind, refc, method);
3995             // Optionally check with the security manager; this isn't needed for unreflect* calls.
3996             if (checkSecurity)
3997                 checkSecurityManager(refc, method);
3998             assert(!method.isMethodHandleInvoke());

3999             if (refKind == REF_invokeSpecial &&
4000                 refc != lookupClass() &&
4001                 !refc.isInterface() &&
4002                 refc != lookupClass().getSuperclass() &&
4003                 refc.isAssignableFrom(lookupClass())) {
4004                 assert(!method.getName().equals("<init>"));  // not this code path
4005 
4006                 // Per JVMS 6.5, desc. of invokespecial instruction:
4007                 // If the method is in a superclass of the LC,
4008                 // and if our original search was above LC.super,
4009                 // repeat the search (symbolic lookup) from LC.super
4010                 // and continue with the direct superclass of that class,
4011                 // and so forth, until a match is found or no further superclasses exist.
4012                 // FIXME: MemberName.resolve should handle this instead.
4013                 Class<?> refcAsSuper = lookupClass();
4014                 MemberName m2;
4015                 do {
4016                     refcAsSuper = refcAsSuper.getSuperclass();
4017                     m2 = new MemberName(refcAsSuper,
4018                                         method.getName(),

4122                     throw getField.makeAccessException("caller class must be a subclass below the method", lookupClass());
4123                 }
4124                 refc = lookupClass();
4125             }
4126             return VarHandles.makeFieldHandle(getField, refc, getField.getFieldType(),
4127                                               this.allowedModes == TRUSTED && !getField.isTrustedFinalField());
4128         }
4129         /** Check access and get the requested constructor. */
4130         private MethodHandle getDirectConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException {
4131             final boolean checkSecurity = true;
4132             return getDirectConstructorCommon(refc, ctor, checkSecurity);
4133         }
4134         /** Check access and get the requested constructor, eliding security manager checks. */
4135         private MethodHandle getDirectConstructorNoSecurityManager(Class<?> refc, MemberName ctor) throws IllegalAccessException {
4136             final boolean checkSecurity = false;  // not needed for reflection or for linking CONSTANT_MH constants
4137             return getDirectConstructorCommon(refc, ctor, checkSecurity);
4138         }
4139         /** Common code for all constructors; do not call directly except from immediately above. */
4140         private MethodHandle getDirectConstructorCommon(Class<?> refc, MemberName ctor,
4141                                                   boolean checkSecurity) throws IllegalAccessException {
4142             assert(ctor.isObjectConstructor());
4143             checkAccess(REF_newInvokeSpecial, refc, ctor);
4144             // Optionally check with the security manager; this isn't needed for unreflect* calls.
4145             if (checkSecurity)
4146                 checkSecurityManager(refc, ctor);
4147             assert(!MethodHandleNatives.isCallerSensitive(ctor));  // maybeBindCaller not relevant here
4148             return DirectMethodHandle.make(ctor).setVarargs(ctor);
4149         }
4150 
4151         /** Hook called from the JVM (via MethodHandleNatives) to link MH constants:
4152          */
4153         /*non-public*/
4154         MethodHandle linkMethodHandleConstant(byte refKind, Class<?> defc, String name, Object type)
4155                 throws ReflectiveOperationException {
4156             if (!(type instanceof Class || type instanceof MethodType))
4157                 throw new InternalError("unresolved MemberName");
4158             MemberName member = new MemberName(refKind, defc, name, type);
4159             MethodHandle mh = LOOKASIDE_TABLE.get(member);
4160             if (mh != null) {
4161                 checkSymbolicClass(defc);
4162                 return mh;

4301      * @param arrayClass an array type
4302      * @return a method handle which can load values from the given array type
4303      * @throws NullPointerException if the argument is null
4304      * @throws  IllegalArgumentException if arrayClass is not an array type
4305      * @jvms 6.5 {@code aaload} Instruction
4306      */
4307     public static MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException {
4308         return MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.GET);
4309     }
4310 
4311     /**
4312      * Produces a method handle giving write access to elements of an array,
4313      * as if by the {@code astore} bytecode.
4314      * The type of the method handle will have a void return type.
4315      * Its last argument will be the array's element type.
4316      * The first and second arguments will be the array type and int.
4317      *
4318      * <p> When the returned method handle is invoked,
4319      * the array reference and array index are checked.
4320      * A {@code NullPointerException} will be thrown if the array reference
4321      * is {@code null} or if the array's element type is a {@link Class#isValueType()
4322      * a primitive value type} and attempts to set {@code null} in the
4323      * array element.  An {@code ArrayIndexOutOfBoundsException} will be
4324      * thrown if the index is negative or if it is greater than or equal to
4325      * the length of the array.
4326      *
4327      * @param arrayClass the class of an array
4328      * @return a method handle which can store values into the array type
4329      * @throws NullPointerException if the argument is null
4330      * @throws IllegalArgumentException if arrayClass is not an array type
4331      * @jvms 6.5 {@code aastore} Instruction
4332      */
4333     public static MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
4334         return MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.SET);
4335     }
4336 
4337     /**
4338      * Produces a VarHandle giving access to elements of an array of type
4339      * {@code arrayClass}.  The VarHandle's variable type is the component type
4340      * of {@code arrayClass} and the list of coordinate types is
4341      * {@code (arrayClass, int)}, where the {@code int} coordinate type
4342      * corresponds to an argument that is an index into an array.
4343      * <p>

5075     }
5076 
5077     /**
5078      * Produces a constant method handle of the requested return type which
5079      * returns the default value for that type every time it is invoked.
5080      * The resulting constant method handle will have no side effects.
5081      * <p>The returned method handle is equivalent to {@code empty(methodType(type))}.
5082      * It is also equivalent to {@code explicitCastArguments(constant(Object.class, null), methodType(type))},
5083      * since {@code explicitCastArguments} converts {@code null} to default values.
5084      * @param type the expected return type of the desired method handle
5085      * @return a constant method handle that takes no arguments
5086      *         and returns the default value of the given type (or void, if the type is void)
5087      * @throws NullPointerException if the argument is null
5088      * @see MethodHandles#constant
5089      * @see MethodHandles#empty
5090      * @see MethodHandles#explicitCastArguments
5091      * @since 9
5092      */
5093     public static MethodHandle zero(Class<?> type) {
5094         Objects.requireNonNull(type);
5095         if (type.isPrimitive()) {
5096             return zero(Wrapper.forPrimitiveType(type), type);
5097         } else if (type.isPrimitiveClass()) {
5098             throw new UnsupportedOperationException();
5099         } else {
5100             return zero(Wrapper.OBJECT, type);
5101         }
5102     }
5103 
5104     private static MethodHandle identityOrVoid(Class<?> type) {
5105         return type == void.class ? zero(type) : identity(type);
5106     }
5107 
5108     /**
5109      * Produces a method handle of the requested type which ignores any arguments, does nothing,
5110      * and returns a suitable default depending on the return type.
5111      * That is, it returns a zero primitive value, a {@code null}, or {@code void}.
5112      * <p>The returned method handle is equivalent to
5113      * {@code dropArguments(zero(type.returnType()), 0, type.parameterList())}.
5114      *
5115      * @apiNote Given a predicate and target, a useful "if-then" construct can be produced as
5116      * {@code guardWithTest(pred, target, empty(target.type())}.
5117      * @param type the type of the desired method handle
5118      * @return a constant method handle of the given type, which returns a default value of the given return type
5119      * @throws NullPointerException if the argument is null
5120      * @see MethodHandles#zero
5121      * @see MethodHandles#constant
5122      * @since 9
5123      */
5124     public static  MethodHandle empty(MethodType type) {
5125         Objects.requireNonNull(type);
5126         return dropArguments(zero(type.returnType()), 0, type.parameterList());
5127     }
5128 
5129     private static final MethodHandle[] IDENTITY_MHS = new MethodHandle[Wrapper.COUNT];
5130     private static MethodHandle makeIdentity(Class<?> ptype) {
5131         MethodType mtype = MethodType.methodType(ptype, ptype);
5132         LambdaForm lform = LambdaForm.identityForm(BasicType.basicType(ptype));
5133         return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.IDENTITY);
5134     }
5135 
5136     private static MethodHandle zero(Wrapper btw, Class<?> rtype) {
5137         int pos = btw.ordinal();
5138         MethodHandle zero = ZERO_MHS[pos];
5139         if (zero == null) {
5140             zero = setCachedMethodHandle(ZERO_MHS, pos, makeZero(btw.primitiveType()));
5141         }
5142         if (zero.type().returnType() == rtype)
5143             return zero;
5144         assert(btw == Wrapper.OBJECT);
5145         return makeZero(rtype);
5146     }
5147     private static final MethodHandle[] ZERO_MHS = new MethodHandle[Wrapper.COUNT];
5148     private static MethodHandle makeZero(Class<?> rtype) {
5149         MethodType mtype = methodType(rtype);
5150         LambdaForm lform = LambdaForm.zeroForm(BasicType.basicType(rtype));
5151         return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.ZERO);
< prev index next >