< prev index next >

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

Print this page

2774          * If the returned method handle is invoked, the constructor's class will
2775          * be initialized, if it has not already been initialized.
2776          * <p><b>Example:</b>
2777          * {@snippet lang="java" :
2778 import static java.lang.invoke.MethodHandles.*;
2779 import static java.lang.invoke.MethodType.*;
2780 ...
2781 MethodHandle MH_newArrayList = publicLookup().findConstructor(
2782   ArrayList.class, methodType(void.class, Collection.class));
2783 Collection orig = Arrays.asList("x", "y");
2784 Collection copy = (ArrayList) MH_newArrayList.invokeExact(orig);
2785 assert(orig != copy);
2786 assertEquals(orig, copy);
2787 // a variable-arity constructor:
2788 MethodHandle MH_newProcessBuilder = publicLookup().findConstructor(
2789   ProcessBuilder.class, methodType(void.class, String[].class));
2790 ProcessBuilder pb = (ProcessBuilder)
2791   MH_newProcessBuilder.invoke("x", "y", "z");
2792 assertEquals("[x, y, z]", pb.command().toString());
2793          * }


2794          * @param refc the class or interface from which the method is accessed
2795          * @param type the type of the method, with the receiver argument omitted, and a void return type
2796          * @return the desired method handle
2797          * @throws NoSuchMethodException if the constructor does not exist
2798          * @throws IllegalAccessException if access checking fails
2799          *                                or if the method's variable arity modifier bit
2800          *                                is set and {@code asVarargsCollector} fails
2801          * @throws    SecurityException if a security manager is present and it
2802          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
2803          * @throws NullPointerException if any argument is null
2804          */
2805         public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
2806             if (refc.isArray()) {
2807                 throw new NoSuchMethodException("no constructor for array class: " + refc.getName());
2808             }



2809             String name = ConstantDescs.INIT_NAME;
2810             MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type);
2811             return getDirectConstructor(refc, ctor);
2812         }
2813 
2814         /**
2815          * Looks up a class by name from the lookup context defined by this {@code Lookup} object,
2816          * <a href="MethodHandles.Lookup.html#equiv">as if resolved</a> by an {@code ldc} instruction.
2817          * Such a resolution, as specified in JVMS {@jvms 5.4.3.1}, attempts to locate and load the class,
2818          * and then determines whether the class is accessible to this lookup object.
2819          * <p>
2820          * For a class or an interface, the name is the {@linkplain ClassLoader##binary-name binary name}.
2821          * For an array class of {@code n} dimensions, the name begins with {@code n} occurrences
2822          * of {@code '['} and followed by the element type as encoded in the
2823          * {@linkplain Class##nameFormat table} specified in {@link Class#getName}.
2824          * <p>
2825          * The lookup context here is determined by the {@linkplain #lookupClass() lookup class},
2826          * its class loader, and the {@linkplain #lookupModes() lookup modes}.
2827          *
2828          * @param targetName the {@linkplain ClassLoader##binary-name binary name} of the class

4057             final boolean doRestrict    = false;
4058             final boolean checkSecurity = true;
4059             return getDirectMethodCommon(REF_invokeSpecial, refc, method, checkSecurity, doRestrict, callerLookup);
4060         }
4061         /** Check access and get the requested method, eliding security manager checks. */
4062         private MethodHandle getDirectMethodNoSecurityManager(byte refKind, Class<?> refc, MemberName method, Lookup callerLookup) throws IllegalAccessException {
4063             final boolean doRestrict    = true;
4064             final boolean checkSecurity = false;  // not needed for reflection or for linking CONSTANT_MH constants
4065             return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerLookup);
4066         }
4067         /** Common code for all methods; do not call directly except from immediately above. */
4068         private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
4069                                                    boolean checkSecurity,
4070                                                    boolean doRestrict,
4071                                                    Lookup boundCaller) throws IllegalAccessException {
4072             checkMethod(refKind, refc, method);
4073             // Optionally check with the security manager; this isn't needed for unreflect* calls.
4074             if (checkSecurity)
4075                 checkSecurityManager(refc, method);
4076             assert(!method.isMethodHandleInvoke());
4077 
4078             if (refKind == REF_invokeSpecial &&
4079                 refc != lookupClass() &&
4080                 !refc.isInterface() && !lookupClass().isInterface() &&
4081                 refc != lookupClass().getSuperclass() &&
4082                 refc.isAssignableFrom(lookupClass())) {
4083                 assert(!method.getName().equals(ConstantDescs.INIT_NAME));  // not this code path
4084 
4085                 // Per JVMS 6.5, desc. of invokespecial instruction:
4086                 // If the method is in a superclass of the LC,
4087                 // and if our original search was above LC.super,
4088                 // repeat the search (symbolic lookup) from LC.super
4089                 // and continue with the direct superclass of that class,
4090                 // and so forth, until a match is found or no further superclasses exist.
4091                 // FIXME: MemberName.resolve should handle this instead.
4092                 Class<?> refcAsSuper = lookupClass();
4093                 MemberName m2;
4094                 do {
4095                     refcAsSuper = refcAsSuper.getSuperclass();
4096                     m2 = new MemberName(refcAsSuper,
4097                                         method.getName(),

2774          * If the returned method handle is invoked, the constructor's class will
2775          * be initialized, if it has not already been initialized.
2776          * <p><b>Example:</b>
2777          * {@snippet lang="java" :
2778 import static java.lang.invoke.MethodHandles.*;
2779 import static java.lang.invoke.MethodType.*;
2780 ...
2781 MethodHandle MH_newArrayList = publicLookup().findConstructor(
2782   ArrayList.class, methodType(void.class, Collection.class));
2783 Collection orig = Arrays.asList("x", "y");
2784 Collection copy = (ArrayList) MH_newArrayList.invokeExact(orig);
2785 assert(orig != copy);
2786 assertEquals(orig, copy);
2787 // a variable-arity constructor:
2788 MethodHandle MH_newProcessBuilder = publicLookup().findConstructor(
2789   ProcessBuilder.class, methodType(void.class, String[].class));
2790 ProcessBuilder pb = (ProcessBuilder)
2791   MH_newProcessBuilder.invoke("x", "y", "z");
2792 assertEquals("[x, y, z]", pb.command().toString());
2793          * }
2794          *
2795          *
2796          * @param refc the class or interface from which the method is accessed
2797          * @param type the type of the method, with the receiver argument omitted, and a void return type
2798          * @return the desired method handle
2799          * @throws NoSuchMethodException if the constructor does not exist
2800          * @throws IllegalAccessException if access checking fails
2801          *                                or if the method's variable arity modifier bit
2802          *                                is set and {@code asVarargsCollector} fails
2803          * @throws    SecurityException if a security manager is present and it
2804          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
2805          * @throws NullPointerException if any argument is null
2806          */
2807         public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
2808             if (refc.isArray()) {
2809                 throw new NoSuchMethodException("no constructor for array class: " + refc.getName());
2810             }
2811             if (type.returnType() != void.class) {
2812                 throw new NoSuchMethodException("Constructors must have void return type: " + refc.getName());
2813             }
2814             String name = ConstantDescs.INIT_NAME;
2815             MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type);
2816             return getDirectConstructor(refc, ctor);
2817         }
2818 
2819         /**
2820          * Looks up a class by name from the lookup context defined by this {@code Lookup} object,
2821          * <a href="MethodHandles.Lookup.html#equiv">as if resolved</a> by an {@code ldc} instruction.
2822          * Such a resolution, as specified in JVMS {@jvms 5.4.3.1}, attempts to locate and load the class,
2823          * and then determines whether the class is accessible to this lookup object.
2824          * <p>
2825          * For a class or an interface, the name is the {@linkplain ClassLoader##binary-name binary name}.
2826          * For an array class of {@code n} dimensions, the name begins with {@code n} occurrences
2827          * of {@code '['} and followed by the element type as encoded in the
2828          * {@linkplain Class##nameFormat table} specified in {@link Class#getName}.
2829          * <p>
2830          * The lookup context here is determined by the {@linkplain #lookupClass() lookup class},
2831          * its class loader, and the {@linkplain #lookupModes() lookup modes}.
2832          *
2833          * @param targetName the {@linkplain ClassLoader##binary-name binary name} of the class

4062             final boolean doRestrict    = false;
4063             final boolean checkSecurity = true;
4064             return getDirectMethodCommon(REF_invokeSpecial, refc, method, checkSecurity, doRestrict, callerLookup);
4065         }
4066         /** Check access and get the requested method, eliding security manager checks. */
4067         private MethodHandle getDirectMethodNoSecurityManager(byte refKind, Class<?> refc, MemberName method, Lookup callerLookup) throws IllegalAccessException {
4068             final boolean doRestrict    = true;
4069             final boolean checkSecurity = false;  // not needed for reflection or for linking CONSTANT_MH constants
4070             return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerLookup);
4071         }
4072         /** Common code for all methods; do not call directly except from immediately above. */
4073         private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
4074                                                    boolean checkSecurity,
4075                                                    boolean doRestrict,
4076                                                    Lookup boundCaller) throws IllegalAccessException {
4077             checkMethod(refKind, refc, method);
4078             // Optionally check with the security manager; this isn't needed for unreflect* calls.
4079             if (checkSecurity)
4080                 checkSecurityManager(refc, method);
4081             assert(!method.isMethodHandleInvoke());

4082             if (refKind == REF_invokeSpecial &&
4083                 refc != lookupClass() &&
4084                 !refc.isInterface() && !lookupClass().isInterface() &&
4085                 refc != lookupClass().getSuperclass() &&
4086                 refc.isAssignableFrom(lookupClass())) {
4087                 assert(!method.getName().equals(ConstantDescs.INIT_NAME));  // not this code path
4088 
4089                 // Per JVMS 6.5, desc. of invokespecial instruction:
4090                 // If the method is in a superclass of the LC,
4091                 // and if our original search was above LC.super,
4092                 // repeat the search (symbolic lookup) from LC.super
4093                 // and continue with the direct superclass of that class,
4094                 // and so forth, until a match is found or no further superclasses exist.
4095                 // FIXME: MemberName.resolve should handle this instead.
4096                 Class<?> refcAsSuper = lookupClass();
4097                 MemberName m2;
4098                 do {
4099                     refcAsSuper = refcAsSuper.getSuperclass();
4100                     m2 = new MemberName(refcAsSuper,
4101                                         method.getName(),
< prev index next >