2645 * If the returned method handle is invoked, the constructor's class will
2646 * be initialized, if it has not already been initialized.
2647 * <p><b>Example:</b>
2648 * {@snippet lang="java" :
2649 import static java.lang.invoke.MethodHandles.*;
2650 import static java.lang.invoke.MethodType.*;
2651 ...
2652 MethodHandle MH_newArrayList = publicLookup().findConstructor(
2653 ArrayList.class, methodType(void.class, Collection.class));
2654 Collection orig = Arrays.asList("x", "y");
2655 Collection copy = (ArrayList) MH_newArrayList.invokeExact(orig);
2656 assert(orig != copy);
2657 assertEquals(orig, copy);
2658 // a variable-arity constructor:
2659 MethodHandle MH_newProcessBuilder = publicLookup().findConstructor(
2660 ProcessBuilder.class, methodType(void.class, String[].class));
2661 ProcessBuilder pb = (ProcessBuilder)
2662 MH_newProcessBuilder.invoke("x", "y", "z");
2663 assertEquals("[x, y, z]", pb.command().toString());
2664 * }
2665 * @param refc the class or interface from which the method is accessed
2666 * @param type the type of the method, with the receiver argument omitted, and a void return type
2667 * @return the desired method handle
2668 * @throws NoSuchMethodException if the constructor does not exist
2669 * @throws IllegalAccessException if access checking fails
2670 * or if the method's variable arity modifier bit
2671 * is set and {@code asVarargsCollector} fails
2672 * @throws NullPointerException if any argument is null
2673 */
2674 public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
2675 if (refc.isArray()) {
2676 throw new NoSuchMethodException("no constructor for array class: " + refc.getName());
2677 }
2678 String name = ConstantDescs.INIT_NAME;
2679 MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type);
2680 return getDirectConstructor(refc, ctor);
2681 }
2682
2683 /**
2684 * Looks up a class by name from the lookup context defined by this {@code Lookup} object,
2685 * <a href="MethodHandles.Lookup.html#equiv">as if resolved</a> by an {@code ldc} instruction.
2686 * Such a resolution, as specified in JVMS {@jvms 5.4.3.1}, attempts to locate and load the class,
2687 * and then determines whether the class is accessible to this lookup object.
2688 * <p>
2689 * For a class or an interface, the name is the {@linkplain ClassLoader##binary-name binary name}.
2690 * For an array class of {@code n} dimensions, the name begins with {@code n} occurrences
2691 * of {@code '['} and followed by the element type as encoded in the
2692 * {@linkplain Class##nameFormat table} specified in {@link Class#getName}.
2693 * <p>
2694 * The lookup context here is determined by the {@linkplain #lookupClass() lookup class},
2695 * its class loader, and the {@linkplain #lookupModes() lookup modes}.
2696 *
2697 * @param targetName the {@linkplain ClassLoader##binary-name binary name} of the class
3824 assert(mh.viewAsTypeChecks(narrowType, true));
3825 return mh.copyWith(narrowType, mh.form);
3826 }
3827
3828 /** Check access and get the requested method. */
3829 private MethodHandle getDirectMethod(byte refKind, Class<?> refc, MemberName method, Lookup callerLookup) throws IllegalAccessException {
3830 final boolean doRestrict = true;
3831 return getDirectMethodCommon(refKind, refc, method, doRestrict, callerLookup);
3832 }
3833 /** Check access and get the requested method, for invokespecial with no restriction on the application of narrowing rules. */
3834 private MethodHandle getDirectMethodNoRestrictInvokeSpecial(Class<?> refc, MemberName method, Lookup callerLookup) throws IllegalAccessException {
3835 final boolean doRestrict = false;
3836 return getDirectMethodCommon(REF_invokeSpecial, refc, method, doRestrict, callerLookup);
3837 }
3838 /** Common code for all methods; do not call directly except from immediately above. */
3839 private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
3840 boolean doRestrict,
3841 Lookup boundCaller) throws IllegalAccessException {
3842 checkMethod(refKind, refc, method);
3843 assert(!method.isMethodHandleInvoke());
3844
3845 if (refKind == REF_invokeSpecial &&
3846 refc != lookupClass() &&
3847 !refc.isInterface() && !lookupClass().isInterface() &&
3848 refc != lookupClass().getSuperclass() &&
3849 refc.isAssignableFrom(lookupClass())) {
3850 assert(!method.getName().equals(ConstantDescs.INIT_NAME)); // not this code path
3851
3852 // Per JVMS 6.5, desc. of invokespecial instruction:
3853 // If the method is in a superclass of the LC,
3854 // and if our original search was above LC.super,
3855 // repeat the search (symbolic lookup) from LC.super
3856 // and continue with the direct superclass of that class,
3857 // and so forth, until a match is found or no further superclasses exist.
3858 // FIXME: MemberName.resolve should handle this instead.
3859 Class<?> refcAsSuper = lookupClass();
3860 MemberName m2;
3861 do {
3862 refcAsSuper = refcAsSuper.getSuperclass();
3863 m2 = new MemberName(refcAsSuper,
3864 method.getName(),
|
2645 * If the returned method handle is invoked, the constructor's class will
2646 * be initialized, if it has not already been initialized.
2647 * <p><b>Example:</b>
2648 * {@snippet lang="java" :
2649 import static java.lang.invoke.MethodHandles.*;
2650 import static java.lang.invoke.MethodType.*;
2651 ...
2652 MethodHandle MH_newArrayList = publicLookup().findConstructor(
2653 ArrayList.class, methodType(void.class, Collection.class));
2654 Collection orig = Arrays.asList("x", "y");
2655 Collection copy = (ArrayList) MH_newArrayList.invokeExact(orig);
2656 assert(orig != copy);
2657 assertEquals(orig, copy);
2658 // a variable-arity constructor:
2659 MethodHandle MH_newProcessBuilder = publicLookup().findConstructor(
2660 ProcessBuilder.class, methodType(void.class, String[].class));
2661 ProcessBuilder pb = (ProcessBuilder)
2662 MH_newProcessBuilder.invoke("x", "y", "z");
2663 assertEquals("[x, y, z]", pb.command().toString());
2664 * }
2665 *
2666 *
2667 * @param refc the class or interface from which the method is accessed
2668 * @param type the type of the method, with the receiver argument omitted, and a void return type
2669 * @return the desired method handle
2670 * @throws NoSuchMethodException if the constructor does not exist
2671 * @throws IllegalAccessException if access checking fails
2672 * or if the method's variable arity modifier bit
2673 * is set and {@code asVarargsCollector} fails
2674 * @throws NullPointerException if any argument is null
2675 */
2676 public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
2677 if (refc.isArray()) {
2678 throw new NoSuchMethodException("no constructor for array class: " + refc.getName());
2679 }
2680 if (type.returnType() != void.class) {
2681 throw new NoSuchMethodException("Constructors must have void return type: " + refc.getName());
2682 }
2683 String name = ConstantDescs.INIT_NAME;
2684 MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type);
2685 return getDirectConstructor(refc, ctor);
2686 }
2687
2688 /**
2689 * Looks up a class by name from the lookup context defined by this {@code Lookup} object,
2690 * <a href="MethodHandles.Lookup.html#equiv">as if resolved</a> by an {@code ldc} instruction.
2691 * Such a resolution, as specified in JVMS {@jvms 5.4.3.1}, attempts to locate and load the class,
2692 * and then determines whether the class is accessible to this lookup object.
2693 * <p>
2694 * For a class or an interface, the name is the {@linkplain ClassLoader##binary-name binary name}.
2695 * For an array class of {@code n} dimensions, the name begins with {@code n} occurrences
2696 * of {@code '['} and followed by the element type as encoded in the
2697 * {@linkplain Class##nameFormat table} specified in {@link Class#getName}.
2698 * <p>
2699 * The lookup context here is determined by the {@linkplain #lookupClass() lookup class},
2700 * its class loader, and the {@linkplain #lookupModes() lookup modes}.
2701 *
2702 * @param targetName the {@linkplain ClassLoader##binary-name binary name} of the class
3829 assert(mh.viewAsTypeChecks(narrowType, true));
3830 return mh.copyWith(narrowType, mh.form);
3831 }
3832
3833 /** Check access and get the requested method. */
3834 private MethodHandle getDirectMethod(byte refKind, Class<?> refc, MemberName method, Lookup callerLookup) throws IllegalAccessException {
3835 final boolean doRestrict = true;
3836 return getDirectMethodCommon(refKind, refc, method, doRestrict, callerLookup);
3837 }
3838 /** Check access and get the requested method, for invokespecial with no restriction on the application of narrowing rules. */
3839 private MethodHandle getDirectMethodNoRestrictInvokeSpecial(Class<?> refc, MemberName method, Lookup callerLookup) throws IllegalAccessException {
3840 final boolean doRestrict = false;
3841 return getDirectMethodCommon(REF_invokeSpecial, refc, method, doRestrict, callerLookup);
3842 }
3843 /** Common code for all methods; do not call directly except from immediately above. */
3844 private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
3845 boolean doRestrict,
3846 Lookup boundCaller) throws IllegalAccessException {
3847 checkMethod(refKind, refc, method);
3848 assert(!method.isMethodHandleInvoke());
3849 if (refKind == REF_invokeSpecial &&
3850 refc != lookupClass() &&
3851 !refc.isInterface() && !lookupClass().isInterface() &&
3852 refc != lookupClass().getSuperclass() &&
3853 refc.isAssignableFrom(lookupClass())) {
3854 assert(!method.getName().equals(ConstantDescs.INIT_NAME)); // not this code path
3855
3856 // Per JVMS 6.5, desc. of invokespecial instruction:
3857 // If the method is in a superclass of the LC,
3858 // and if our original search was above LC.super,
3859 // repeat the search (symbolic lookup) from LC.super
3860 // and continue with the direct superclass of that class,
3861 // and so forth, until a match is found or no further superclasses exist.
3862 // FIXME: MemberName.resolve should handle this instead.
3863 Class<?> refcAsSuper = lookupClass();
3864 MemberName m2;
3865 do {
3866 refcAsSuper = refcAsSuper.getSuperclass();
3867 m2 = new MemberName(refcAsSuper,
3868 method.getName(),
|