< prev index next >

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

Print this page

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

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

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






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

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







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



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

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









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

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



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

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

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

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

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

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


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

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






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

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

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

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

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

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

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

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

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

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

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

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

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