< prev index next >

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

Print this page

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


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



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

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

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

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

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