< prev index next >

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

Print this page
*** 33,10 ***
--- 33,11 ---
  import jdk.internal.org.objectweb.asm.Type;
  import jdk.internal.reflect.CallerSensitive;
  import jdk.internal.reflect.CallerSensitiveAdapter;
  import jdk.internal.reflect.Reflection;
  import jdk.internal.util.ClassFileDumper;
+ import jdk.internal.value.ValueClass;
  import jdk.internal.vm.annotation.ForceInline;
  import sun.invoke.util.ValueConversions;
  import sun.invoke.util.VerifyAccess;
  import sun.invoke.util.Wrapper;
  import sun.reflect.misc.ReflectUtil;

*** 703,11 ***
       * the current class.  Again, this requirement is enforced by narrowing the
       * type of the leading parameter to the resulting method handle.
       * (See the Java Virtual Machine Specification, section {@jvms 4.10.1.9}.)
       * <p>
       * The JVM represents constructors and static initializer blocks as internal methods
!      * with special names ({@value ConstantDescs#INIT_NAME} and {@value
       * ConstantDescs#CLASS_INIT_NAME}).
       * The internal syntax of invocation instructions allows them to refer to such internal
       * methods as if they were normal methods, but the JVM bytecode verifier rejects them.
       * A lookup of such an internal method will produce a {@code NoSuchMethodException}.
       * <p>
--- 704,11 ---
       * the current class.  Again, this requirement is enforced by narrowing the
       * type of the leading parameter to the resulting method handle.
       * (See the Java Virtual Machine Specification, section {@jvms 4.10.1.9}.)
       * <p>
       * The JVM represents constructors and static initializer blocks as internal methods
!      * with special names ({@value ConstantDescs#INIT_NAME}, and {@value
       * ConstantDescs#CLASS_INIT_NAME}).
       * The internal syntax of invocation instructions allows them to refer to such internal
       * methods as if they were normal methods, but the JVM bytecode verifier rejects them.
       * A lookup of such an internal method will produce a {@code NoSuchMethodException}.
       * <p>

*** 2801,10 ***
--- 2802,12 ---
    ProcessBuilder.class, methodType(void.class, String[].class));
  ProcessBuilder pb = (ProcessBuilder)
    MH_newProcessBuilder.invoke("x", "y", "z");
  assertEquals("[x, y, z]", pb.command().toString());
           * }
+          *
+          *
           * @param refc the class or interface from which the method is accessed
           * @param type the type of the method, with the receiver argument omitted, and a void return type
           * @return the desired method handle
           * @throws NoSuchMethodException if the constructor does not exist
           * @throws IllegalAccessException if access checking fails

*** 2816,10 ***
--- 2819,13 ---
           */
          public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
              if (refc.isArray()) {
                  throw new NoSuchMethodException("no constructor for array class: " + refc.getName());
              }
+             if (type.returnType() != void.class) {
+                 throw new NoSuchMethodException("Constructors must have void return type: " + refc.getName());
+             }
              String name = ConstantDescs.INIT_NAME;
              MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type);
              return getDirectConstructor(refc, ctor);
          }
  

*** 3511,25 ***
           *                                is set and {@code asVarargsCollector} fails
           * @throws NullPointerException if the argument is null
           */
          public MethodHandle unreflectConstructor(Constructor<?> c) throws IllegalAccessException {
              MemberName ctor = new MemberName(c);
!             assert(ctor.isConstructor());
              @SuppressWarnings("deprecation")
              Lookup lookup = c.isAccessible() ? IMPL_LOOKUP : this;
!             return lookup.getDirectConstructorNoSecurityManager(ctor.getDeclaringClass(), ctor);
          }
  
          /*
           * Produces a method handle that is capable of creating instances of the given class
           * and instantiated by the given constructor.  No security manager check.
           *
           * This method should only be used by ReflectionFactory::newConstructorForSerialization.
           */
          /* package-private */ MethodHandle serializableConstructor(Class<?> decl, Constructor<?> c) throws IllegalAccessException {
              MemberName ctor = new MemberName(c);
!             assert(ctor.isConstructor() && constructorInSuperclass(decl, c));
              checkAccess(REF_newInvokeSpecial, decl, ctor);
              assert(!MethodHandleNatives.isCallerSensitive(ctor));  // maybeBindCaller not relevant here
              return DirectMethodHandle.makeAllocator(decl, ctor).setVarargs(ctor);
          }
  
--- 3517,25 ---
           *                                is set and {@code asVarargsCollector} fails
           * @throws NullPointerException if the argument is null
           */
          public MethodHandle unreflectConstructor(Constructor<?> c) throws IllegalAccessException {
              MemberName ctor = new MemberName(c);
!             assert(ctor.isObjectConstructor());
              @SuppressWarnings("deprecation")
              Lookup lookup = c.isAccessible() ? IMPL_LOOKUP : this;
!             return lookup.getDirectConstructorNoSecurityManager(c.getDeclaringClass(), ctor);
          }
  
          /*
           * Produces a method handle that is capable of creating instances of the given class
           * and instantiated by the given constructor.  No security manager check.
           *
           * This method should only be used by ReflectionFactory::newConstructorForSerialization.
           */
          /* package-private */ MethodHandle serializableConstructor(Class<?> decl, Constructor<?> c) throws IllegalAccessException {
              MemberName ctor = new MemberName(c);
!             assert(ctor.isObjectConstructor() && constructorInSuperclass(decl, c));
              checkAccess(REF_newInvokeSpecial, decl, ctor);
              assert(!MethodHandleNatives.isCallerSensitive(ctor));  // maybeBindCaller not relevant here
              return DirectMethodHandle.makeAllocator(decl, ctor).setVarargs(ctor);
          }
  

*** 3789,10 ***
--- 3795,11 ---
              Objects.requireNonNull(type);
              // implicit null-check of name
              if (name.startsWith("<") && refKind != REF_newInvokeSpecial) {
                  return null;
              }
+ 
              return IMPL_NAMES.resolveOrNull(refKind, new MemberName(refc, name, type, refKind), lookupClassOrNull(), allowedModes);
          }
  
          void checkSymbolicClass(Class<?> refc) throws IllegalAccessException {
              if (!isClassAccessible(refc)) {

*** 3811,11 ***
          }
  
          /** Check name for an illegal leading "&lt;" character. */
          void checkMethodName(byte refKind, String name) throws NoSuchMethodException {
              if (name.startsWith("<") && refKind != REF_newInvokeSpecial)
!                 throw new NoSuchMethodException("illegal method name: "+name);
          }
  
          /**
           * Find my trustable caller class if m is a caller sensitive method.
           * If this lookup object has original full privilege access, then the caller class is the lookupClass.
--- 3818,11 ---
          }
  
          /** Check name for an illegal leading "&lt;" character. */
          void checkMethodName(byte refKind, String name) throws NoSuchMethodException {
              if (name.startsWith("<") && refKind != REF_newInvokeSpecial)
!                 throw new NoSuchMethodException("illegal method name: " + name + " ref kind " + refKind);
          }
  
          /**
           * Find my trustable caller class if m is a caller sensitive method.
           * If this lookup object has original full privilege access, then the caller class is the lookupClass.

*** 3923,11 ***
          }
  
          void checkMethod(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException {
              boolean wantStatic = (refKind == REF_invokeStatic);
              String message;
!             if (m.isConstructor())
                  message = "expected a method, not a constructor";
              else if (!m.isMethod())
                  message = "expected a method";
              else if (wantStatic != m.isStatic())
                  message = wantStatic ? "expected a static method" : "expected a non-static method";
--- 3930,11 ---
          }
  
          void checkMethod(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException {
              boolean wantStatic = (refKind == REF_invokeStatic);
              String message;
!             if (m.isObjectConstructor())
                  message = "expected a method, not a constructor";
              else if (!m.isMethod())
                  message = "expected a method";
              else if (wantStatic != m.isStatic())
                  message = wantStatic ? "expected a static method" : "expected a non-static method";

*** 4084,11 ***
              checkMethod(refKind, refc, method);
              // Optionally check with the security manager; this isn't needed for unreflect* calls.
              if (checkSecurity)
                  checkSecurityManager(refc, method);
              assert(!method.isMethodHandleInvoke());
- 
              if (refKind == REF_invokeSpecial &&
                  refc != lookupClass() &&
                  !refc.isInterface() && !lookupClass().isInterface() &&
                  refc != lookupClass().getSuperclass() &&
                  refc.isAssignableFrom(lookupClass())) {
--- 4091,10 ---

*** 4233,11 ***
              return getDirectConstructorCommon(refc, ctor, checkSecurity);
          }
          /** Common code for all constructors; do not call directly except from immediately above. */
          private MethodHandle getDirectConstructorCommon(Class<?> refc, MemberName ctor,
                                                    boolean checkSecurity) throws IllegalAccessException {
!             assert(ctor.isConstructor());
              checkAccess(REF_newInvokeSpecial, refc, ctor);
              // Optionally check with the security manager; this isn't needed for unreflect* calls.
              if (checkSecurity)
                  checkSecurityManager(refc, ctor);
              assert(!MethodHandleNatives.isCallerSensitive(ctor));  // maybeBindCaller not relevant here
--- 4239,11 ---
              return getDirectConstructorCommon(refc, ctor, checkSecurity);
          }
          /** Common code for all constructors; do not call directly except from immediately above. */
          private MethodHandle getDirectConstructorCommon(Class<?> refc, MemberName ctor,
                                                    boolean checkSecurity) throws IllegalAccessException {
!             assert(ctor.isObjectConstructor());
              checkAccess(REF_newInvokeSpecial, refc, ctor);
              // Optionally check with the security manager; this isn't needed for unreflect* calls.
              if (checkSecurity)
                  checkSecurityManager(refc, ctor);
              assert(!MethodHandleNatives.isCallerSensitive(ctor));  // maybeBindCaller not relevant here

*** 5184,11 ***
       * @see MethodHandles#explicitCastArguments
       * @since 9
       */
      public static MethodHandle zero(Class<?> type) {
          Objects.requireNonNull(type);
!         return type.isPrimitive() ?  zero(Wrapper.forPrimitiveType(type), type) : zero(Wrapper.OBJECT, type);
      }
  
      private static MethodHandle identityOrVoid(Class<?> type) {
          return type == void.class ? zero(type) : identity(type);
      }
--- 5190,16 ---
       * @see MethodHandles#explicitCastArguments
       * @since 9
       */
      public static MethodHandle zero(Class<?> type) {
          Objects.requireNonNull(type);
!         // TODO: implicitly constructible value class
+         if (type.isPrimitive()) {
+             return zero(Wrapper.forPrimitiveType(type), type);
+         } else {
+             return zero(Wrapper.OBJECT, type);
+         }
      }
  
      private static MethodHandle identityOrVoid(Class<?> type) {
          return type == void.class ? zero(type) : identity(type);
      }

*** 5214,11 ***
          return dropArgumentsTrusted(zero(type.returnType()), 0, type.ptypes());
      }
  
      private static final MethodHandle[] IDENTITY_MHS = new MethodHandle[Wrapper.COUNT];
      private static MethodHandle makeIdentity(Class<?> ptype) {
!         MethodType mtype = methodType(ptype, ptype);
          LambdaForm lform = LambdaForm.identityForm(BasicType.basicType(ptype));
          return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.IDENTITY);
      }
  
      private static MethodHandle zero(Wrapper btw, Class<?> rtype) {
--- 5225,11 ---
          return dropArgumentsTrusted(zero(type.returnType()), 0, type.ptypes());
      }
  
      private static final MethodHandle[] IDENTITY_MHS = new MethodHandle[Wrapper.COUNT];
      private static MethodHandle makeIdentity(Class<?> ptype) {
!         MethodType mtype = MethodType.methodType(ptype, ptype);
          LambdaForm lform = LambdaForm.identityForm(BasicType.basicType(ptype));
          return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.IDENTITY);
      }
  
      private static MethodHandle zero(Wrapper btw, Class<?> rtype) {
< prev index next >