< prev index next >

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

Print this page

2646          * If the returned method handle is invoked, the constructor's class will
2647          * be initialized, if it has not already been initialized.
2648          * <p><b>Example:</b>
2649          * {@snippet lang="java" :
2650 import static java.lang.invoke.MethodHandles.*;
2651 import static java.lang.invoke.MethodType.*;
2652 ...
2653 MethodHandle MH_newArrayList = publicLookup().findConstructor(
2654   ArrayList.class, methodType(void.class, Collection.class));
2655 Collection orig = Arrays.asList("x", "y");
2656 Collection copy = (ArrayList) MH_newArrayList.invokeExact(orig);
2657 assert(orig != copy);
2658 assertEquals(orig, copy);
2659 // a variable-arity constructor:
2660 MethodHandle MH_newProcessBuilder = publicLookup().findConstructor(
2661   ProcessBuilder.class, methodType(void.class, String[].class));
2662 ProcessBuilder pb = (ProcessBuilder)
2663   MH_newProcessBuilder.invoke("x", "y", "z");
2664 assertEquals("[x, y, z]", pb.command().toString());
2665          * }


2666          * @param refc the class or interface from which the method is accessed
2667          * @param type the type of the method, with the receiver argument omitted, and a void return type
2668          * @return the desired method handle
2669          * @throws NoSuchMethodException if the constructor does not exist
2670          * @throws IllegalAccessException if access checking fails
2671          *                                or if the method's variable arity modifier bit
2672          *                                is set and {@code asVarargsCollector} fails
2673          * @throws NullPointerException if any argument is null
2674          */
2675         public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
2676             if (refc.isArray()) {
2677                 throw new NoSuchMethodException("no constructor for array class: " + refc.getName());
2678             }



2679             String name = ConstantDescs.INIT_NAME;
2680             MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type);
2681             return getDirectConstructor(refc, ctor);
2682         }
2683 
2684         /**
2685          * Looks up a class by name from the lookup context defined by this {@code Lookup} object,
2686          * <a href="MethodHandles.Lookup.html#equiv">as if resolved</a> by an {@code ldc} instruction.
2687          * Such a resolution, as specified in JVMS {@jvms 5.4.3.1}, attempts to locate and load the class,
2688          * and then determines whether the class is accessible to this lookup object.
2689          * <p>
2690          * For a class or an interface, the name is the {@linkplain ClassLoader##binary-name binary name}.
2691          * For an array class of {@code n} dimensions, the name begins with {@code n} occurrences
2692          * of {@code '['} and followed by the element type as encoded in the
2693          * {@linkplain Class##nameFormat table} specified in {@link Class#getName}.
2694          * <p>
2695          * The lookup context here is determined by the {@linkplain #lookupClass() lookup class},
2696          * its class loader, and the {@linkplain #lookupModes() lookup modes}.
2697          *
2698          * @param targetName the {@linkplain ClassLoader##binary-name binary name} of the class

3825             assert(mh.viewAsTypeChecks(narrowType, true));
3826             return mh.copyWith(narrowType, mh.form);
3827         }
3828 
3829         /** Check access and get the requested method. */
3830         private MethodHandle getDirectMethod(byte refKind, Class<?> refc, MemberName method, Lookup callerLookup) throws IllegalAccessException {
3831             final boolean doRestrict    = true;
3832             return getDirectMethodCommon(refKind, refc, method, doRestrict, callerLookup);
3833         }
3834         /** Check access and get the requested method, for invokespecial with no restriction on the application of narrowing rules. */
3835         private MethodHandle getDirectMethodNoRestrictInvokeSpecial(Class<?> refc, MemberName method, Lookup callerLookup) throws IllegalAccessException {
3836             final boolean doRestrict    = false;
3837             return getDirectMethodCommon(REF_invokeSpecial, refc, method, doRestrict, callerLookup);
3838         }
3839         /** Common code for all methods; do not call directly except from immediately above. */
3840         private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
3841                                                    boolean doRestrict,
3842                                                    Lookup boundCaller) throws IllegalAccessException {
3843             checkMethod(refKind, refc, method);
3844             assert(!method.isMethodHandleInvoke());
3845 
3846             if (refKind == REF_invokeSpecial &&
3847                 refc != lookupClass() &&
3848                 !refc.isInterface() && !lookupClass().isInterface() &&
3849                 refc != lookupClass().getSuperclass() &&
3850                 refc.isAssignableFrom(lookupClass())) {
3851                 assert(!method.getName().equals(ConstantDescs.INIT_NAME));  // not this code path
3852 
3853                 // Per JVMS 6.5, desc. of invokespecial instruction:
3854                 // If the method is in a superclass of the LC,
3855                 // and if our original search was above LC.super,
3856                 // repeat the search (symbolic lookup) from LC.super
3857                 // and continue with the direct superclass of that class,
3858                 // and so forth, until a match is found or no further superclasses exist.
3859                 // FIXME: MemberName.resolve should handle this instead.
3860                 Class<?> refcAsSuper = lookupClass();
3861                 MemberName m2;
3862                 do {
3863                     refcAsSuper = refcAsSuper.getSuperclass();
3864                     m2 = new MemberName(refcAsSuper,
3865                                         method.getName(),

2646          * If the returned method handle is invoked, the constructor's class will
2647          * be initialized, if it has not already been initialized.
2648          * <p><b>Example:</b>
2649          * {@snippet lang="java" :
2650 import static java.lang.invoke.MethodHandles.*;
2651 import static java.lang.invoke.MethodType.*;
2652 ...
2653 MethodHandle MH_newArrayList = publicLookup().findConstructor(
2654   ArrayList.class, methodType(void.class, Collection.class));
2655 Collection orig = Arrays.asList("x", "y");
2656 Collection copy = (ArrayList) MH_newArrayList.invokeExact(orig);
2657 assert(orig != copy);
2658 assertEquals(orig, copy);
2659 // a variable-arity constructor:
2660 MethodHandle MH_newProcessBuilder = publicLookup().findConstructor(
2661   ProcessBuilder.class, methodType(void.class, String[].class));
2662 ProcessBuilder pb = (ProcessBuilder)
2663   MH_newProcessBuilder.invoke("x", "y", "z");
2664 assertEquals("[x, y, z]", pb.command().toString());
2665          * }
2666          *
2667          *
2668          * @param refc the class or interface from which the method is accessed
2669          * @param type the type of the method, with the receiver argument omitted, and a void return type
2670          * @return the desired method handle
2671          * @throws NoSuchMethodException if the constructor does not exist
2672          * @throws IllegalAccessException if access checking fails
2673          *                                or if the method's variable arity modifier bit
2674          *                                is set and {@code asVarargsCollector} fails
2675          * @throws NullPointerException if any argument is null
2676          */
2677         public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
2678             if (refc.isArray()) {
2679                 throw new NoSuchMethodException("no constructor for array class: " + refc.getName());
2680             }
2681             if (type.returnType() != void.class) {
2682                 throw new NoSuchMethodException("Constructors must have void return type: " + refc.getName());
2683             }
2684             String name = ConstantDescs.INIT_NAME;
2685             MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type);
2686             return getDirectConstructor(refc, ctor);
2687         }
2688 
2689         /**
2690          * Looks up a class by name from the lookup context defined by this {@code Lookup} object,
2691          * <a href="MethodHandles.Lookup.html#equiv">as if resolved</a> by an {@code ldc} instruction.
2692          * Such a resolution, as specified in JVMS {@jvms 5.4.3.1}, attempts to locate and load the class,
2693          * and then determines whether the class is accessible to this lookup object.
2694          * <p>
2695          * For a class or an interface, the name is the {@linkplain ClassLoader##binary-name binary name}.
2696          * For an array class of {@code n} dimensions, the name begins with {@code n} occurrences
2697          * of {@code '['} and followed by the element type as encoded in the
2698          * {@linkplain Class##nameFormat table} specified in {@link Class#getName}.
2699          * <p>
2700          * The lookup context here is determined by the {@linkplain #lookupClass() lookup class},
2701          * its class loader, and the {@linkplain #lookupModes() lookup modes}.
2702          *
2703          * @param targetName the {@linkplain ClassLoader##binary-name binary name} of the class

3830             assert(mh.viewAsTypeChecks(narrowType, true));
3831             return mh.copyWith(narrowType, mh.form);
3832         }
3833 
3834         /** Check access and get the requested method. */
3835         private MethodHandle getDirectMethod(byte refKind, Class<?> refc, MemberName method, Lookup callerLookup) throws IllegalAccessException {
3836             final boolean doRestrict    = true;
3837             return getDirectMethodCommon(refKind, refc, method, doRestrict, callerLookup);
3838         }
3839         /** Check access and get the requested method, for invokespecial with no restriction on the application of narrowing rules. */
3840         private MethodHandle getDirectMethodNoRestrictInvokeSpecial(Class<?> refc, MemberName method, Lookup callerLookup) throws IllegalAccessException {
3841             final boolean doRestrict    = false;
3842             return getDirectMethodCommon(REF_invokeSpecial, refc, method, doRestrict, callerLookup);
3843         }
3844         /** Common code for all methods; do not call directly except from immediately above. */
3845         private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
3846                                                    boolean doRestrict,
3847                                                    Lookup boundCaller) throws IllegalAccessException {
3848             checkMethod(refKind, refc, method);
3849             assert(!method.isMethodHandleInvoke());

3850             if (refKind == REF_invokeSpecial &&
3851                 refc != lookupClass() &&
3852                 !refc.isInterface() && !lookupClass().isInterface() &&
3853                 refc != lookupClass().getSuperclass() &&
3854                 refc.isAssignableFrom(lookupClass())) {
3855                 assert(!method.getName().equals(ConstantDescs.INIT_NAME));  // not this code path
3856 
3857                 // Per JVMS 6.5, desc. of invokespecial instruction:
3858                 // If the method is in a superclass of the LC,
3859                 // and if our original search was above LC.super,
3860                 // repeat the search (symbolic lookup) from LC.super
3861                 // and continue with the direct superclass of that class,
3862                 // and so forth, until a match is found or no further superclasses exist.
3863                 // FIXME: MemberName.resolve should handle this instead.
3864                 Class<?> refcAsSuper = lookupClass();
3865                 MemberName m2;
3866                 do {
3867                     refcAsSuper = refcAsSuper.getSuperclass();
3868                     m2 = new MemberName(refcAsSuper,
3869                                         method.getName(),
< prev index next >