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