Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8282718

Add API to get the MethodType of an Executable

XMLWordPrintable

      A DESCRIPTION OF THE PROBLEM :
      h1. Add API to get the {{java.lang.invoke.MethodType}} of a {{java.lang.reflect.Executable}}

      h2. Summary

      Add a public method to {{java.lang.reflect.Executable}} to get the {{java.lang.invoke.MethodType}} of the executable.

      h2. Problem

      Getting a {{MethodType}} for a {{java.lang.reflect.Method}} or a {{java.lang.reflect.Constructor}} currently requires calling {{Executable.getParameterTypes()}}, which clones the parameters array, and then calling {{MethodType.methodType(Class<?> rtype, Class<?>[] ptypes)}}, which clones the {{ptypes}} array again, and also the {{MethodType}} instance, if a cache miss occurs in {{MethodType.makeImpl}}.
      If this method were implemented in {{java.lang.reflect.Method}} and {{java.lang.reflect.Constructor}}, then the cloning of the parameters array and uncached {{MethodType}}s could be eliminated.

      h2. Solution

      Add the {{public abstract java.lang.invoke.MethodType methodType()}} method to {{java.lang.reflect.Executable}}, with concrete implementations provided in {{java.lang.reflect.Method}} and {{java.lang.reflect.Constructor}}.

      h2. Specification

      {code:none}
      diff --git a/src/java.base/share/classes/java/lang/invoke/MemberName.java b/src/java.base/share/classes/java/lang/invoke/MemberName.java
      --- a/src/java.base/share/classes/java/lang/invoke/MemberName.java
      +++ b/src/java.base/share/classes/java/lang/invoke/MemberName.java
      @@ -588,7 +588,7 @@ final class MemberName implements Member, Cloneable {
                       // The JVM did not reify this signature-polymorphic instance.
                       // Need a special case here.
                       // See comments on MethodHandleNatives.linkMethod.
      - MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
      + MethodType type = m.methodType();
                       int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual);
                       init(MethodHandle.class, m.getName(), type, flags);
                       if (isMethodHandleInvoke())
      @@ -599,7 +599,7 @@ final class MemberName implements Member, Cloneable {
                       // The JVM did not reify this signature-polymorphic instance.
                       // Need a special case here.
                       // See comments on MethodHandleNatives.linkMethod.
      - MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
      + MethodType type = m.methodType();
                       int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual);
                       init(VarHandle.class, m.getName(), type, flags);
                       if (isVarHandleMethodInvoke())
      diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
      --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
      +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
      @@ -1671,6 +1671,11 @@ abstract class MethodHandleImpl {
                   public Class<?>[] exceptionTypes(MethodHandle handle) {
                       return VarHandles.exceptionTypes(handle);
                   }
      +
      + @Override
      + public MethodType makeMethodType(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
      + return MethodType.makeImpl(rtype, ptypes, trusted);
      + }
               });
           }
       
      diff --git a/src/java.base/share/classes/java/lang/reflect/Constructor.java b/src/java.base/share/classes/java/lang/reflect/Constructor.java
      --- a/src/java.base/share/classes/java/lang/reflect/Constructor.java
      +++ b/src/java.base/share/classes/java/lang/reflect/Constructor.java
      @@ -40,6 +40,7 @@ import sun.reflect.generics.factory.GenericsFactory;
       import sun.reflect.generics.scope.ConstructorScope;
       import java.lang.annotation.Annotation;
       import java.lang.annotation.AnnotationFormatError;
      +import java.lang.invoke.MethodType;
       import java.util.StringJoiner;
       
       /**
      @@ -270,8 +271,19 @@ public final class Constructor<T> extends Executable {
            * {@inheritDoc}
            * @since 1.8
            */
      + @Override
           public int getParameterCount() { return parameterTypes.length; }
       
      + /**
      + * {@inheritDoc}
      + * @since 19
      + */
      + @Override
      + public MethodType methodType() {
      + return SharedSecrets.getJavaLangInvokeAccess().
      + makeMethodType(void.class, parameterTypes.clone(), true);
      + }
      +
           /**
            * {@inheritDoc}
            * @throws GenericSignatureFormatError {@inheritDoc}
      diff --git a/src/java.base/share/classes/java/lang/reflect/Executable.java b/src/java.base/share/classes/java/lang/reflect/Executable.java
      --- a/src/java.base/share/classes/java/lang/reflect/Executable.java
      +++ b/src/java.base/share/classes/java/lang/reflect/Executable.java
      @@ -26,6 +26,7 @@
       package java.lang.reflect;
       
       import java.lang.annotation.*;
      +import java.lang.invoke.MethodType;
       import java.util.Arrays;
       import java.util.Map;
       import java.util.Objects;
      @@ -257,6 +258,15 @@ public abstract sealed class Executable extends AccessibleObject
               throw new AbstractMethodError();
           }
       
      + /**
      + * Returns the {@link MethodType} for the executable represented by this
      + * object.
      + *
      + * @return The {@link MethodType} for the executable this object represents
      + * @since 19
      + */
      + public abstract MethodType methodType();
      +
           /**
            * Returns an array of {@code Type} objects that represent the
            * formal parameter types, in declaration order, of the executable
      diff --git a/src/java.base/share/classes/java/lang/reflect/Method.java b/src/java.base/share/classes/java/lang/reflect/Method.java
      --- a/src/java.base/share/classes/java/lang/reflect/Method.java
      +++ b/src/java.base/share/classes/java/lang/reflect/Method.java
      @@ -44,6 +44,7 @@ import sun.reflect.annotation.AnnotationType;
       import sun.reflect.annotation.AnnotationParser;
       import java.lang.annotation.Annotation;
       import java.lang.annotation.AnnotationFormatError;
      +import java.lang.invoke.MethodType;
       import java.nio.ByteBuffer;
       import java.util.StringJoiner;
       
      @@ -319,8 +320,18 @@ public final class Method extends Executable {
            * {@inheritDoc}
            * @since 1.8
            */
      + @Override
           public int getParameterCount() { return parameterTypes.length; }
       
      + /**
      + * {@inheritDoc}
      + * @since 19
      + */
      + @Override
      + public MethodType methodType() {
      + return SharedSecrets.getJavaLangInvokeAccess().
      + makeMethodType(returnType, parameterTypes.clone(), true);
      + }
       
           /**
            * {@inheritDoc}
      diff --git a/src/java.base/share/classes/jdk/internal/access/JavaLangInvokeAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaLangInvokeAccess.java
      --- a/src/java.base/share/classes/jdk/internal/access/JavaLangInvokeAccess.java
      +++ b/src/java.base/share/classes/jdk/internal/access/JavaLangInvokeAccess.java
      @@ -188,4 +188,10 @@ public interface JavaLangInvokeAccess {
            * @return an array of exceptions, or {@code null}.
            */
           Class<?>[] exceptionTypes(MethodHandle handle);
      +
      + /**
      + * Returns the {@code MethodType} for the given return and parameter types.
      + * If {@code trusted} is true, then the ptypes array is not cloned.
      + */
      + MethodType makeMethodType(Class<?> rtype, Class<?>[] ptypes, boolean trusted);
       }
      {code}


            liach Chen Liang
            webbuggrp Webbug Group
            Votes:
            1 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: