方法调用8——MethodHandle方法调用实现原理

public class PolymorphicSignatureTest {
    public int calculate(int num) {
        return num + 1;
    }

    public double calculate(double num) {
        return num + 1;
    }

    public double calculate(Integer num) {
        return num + 1;
    }

    public static void main(String[] args) throws Throwable{
        MethodType mt = MethodType.methodType(int.class, int.class);
        MethodHandle mh =  MethodHandles.lookup()
                .findVirtual(PolymorphicSignatureTest.class, "calculate", mt)
                .bindTo(new PolymorphicSignatureTest());
        int result1 = (int)mh.invoke(1);
        double resultE = (double)mh.invokeExact(1);
        double result2 = (double)mh.invoke(1);
        double result3 = (double)mh.invoke(Integer.valueOf(1));
        System.out.println(result1);
        System.out.println(result2);
        System.out.println(result3);
    }
}

字节码:

        34: invokevirtual #11                 // Method java/lang/invoke/MethodHandle.invoke:(I)I

        40: invokevirtual #12                 // Method java/lang/invoke/MethodHandle.invokeExact:(I)D

        47: invokevirtual #13                 // Method java/lang/invoke/MethodHandle.invoke:(I)D

        57: invokevirtual #15                 // Method java/lang/invoke/MethodHandle.invoke:(Ljava/lang/Integer;)D

其中符号类型描述符为:

(I)I
(I)D
(I)D
(Ljava/lang/Integer;)D

1 MethodHandle实现

通过新建异常实例来查看栈轨迹:

    public int calculate(int num) {
        new Exception().printStackTrace();
        return num + 1;
    }

启用-XX:+UnlockDiagnosticVMOptions -XX:+ShowHiddenFrames虚拟机参数来打印隐藏的栈信息:

-XX:+UnlockDiagnosticVMOptions
-XX:+ShowHiddenFrames

结果:

java.lang.Exception
    at com.enjoy.learn.core.oop.method.PolymorphicSignatureTest.calculate(PolymorphicSignatureTest.java:16)
    at java.lang.invoke.LambdaForm$DMH006/2055281021.invokeVirtual_001_LI_I(LambdaForm$DMH006:1000011)
    at java.lang.invoke.LambdaForm$BMH002/1160460865.reinvoke_002(LambdaForm$BMH002:1000021)
    at java.lang.invoke.LambdaForm$MH012/1421795058.invoke_000_MT(LambdaForm$MH012:1000017)
    at com.enjoy.learn.core.oop.method.PolymorphicSignatureTest.main(PolymorphicSignatureTest.java:35)

添加JVM参数导出class文件:

-Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=true

LambdaForm$MH012文件反编译如下:

final class LambdaForm$MH012
{
  @LambdaForm.Hidden
  @LambdaForm.Compiled
  @ForceInline
  static double invoke_000_MT(Object paramObject1, int paramInt, Object paramObject2)
  {
    Object localObject = Invokers.checkGenericType(paramObject1, paramObject2);
    Invokers.checkCustomized(localObject);
    return (localObject = (MethodHandle)localObject).invokeBasic(paramInt);
  }
  
  static void dummy()
  {
    "invoke_000_MT=Lambda(a0:L,a1:I,a2:L)=>{\n    t3:L=Invokers.checkGenericType(a0:L,a2:L);\n    t4:V=Invokers.checkCustomized(t3:L);\n    t5:D=MethodHandle.invokeBasic(t3:L,a1:I);t5:D}";
  }
}

该方法的三个步骤:
step1.Invokers.checkGenericType方法类型检查
step2.Invokers.checkCustomized在MethodHandle执行次数超过一个阈值时进行优化(-Djava.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD,默认为127)
step3.调用MethodHandle的invokeBasic。调用至MethodHandle所持有的的适配器中,同样是LambdaForm

    /**
     * Private method for trusted invocation of a method handle respecting simplified signatures.
     * Type mismatches will not throw {@code WrongMethodTypeException}, but could crash the JVM.
     * 

* The caller signature is restricted to the following basic types: * Object, int, long, float, double, and void return. *

* The caller is responsible for maintaining type correctness by ensuring * that the each outgoing argument value is a member of the range of the corresponding * callee argument type. * (The caller should therefore issue appropriate casts and integer narrowing * operations on outgoing argument values.) * The caller can assume that the incoming result value is part of the range * of the callee's return type. * @param args the signature-polymorphic parameter list, statically represented using varargs * @return the signature-polymorphic result, statically represented using {@code Object} */ /*non-public*/ final native @PolymorphicSignature Object invokeBasic(Object... args) throws Throwable;

LambdaForm$BMH002文件:

final class LambdaForm$BMH002
{
  @LambdaForm.Hidden
  @LambdaForm.Compiled
  @ForceInline
  static double reinvoke_002(Object paramObject, int paramInt)
  {
    Object localObject1 = (paramObject = (BoundMethodHandle.Species_L3)paramObject).argL1;
    Object localObject2 = ((BoundMethodHandle.Species_L3)paramObject).argL0;
    int i = ((MethodHandle)localObject2).invokeBasic(localObject1, paramInt);
    Object localObject3 = ((BoundMethodHandle.Species_L3)paramObject).argL2;
    return ((MethodHandle)localObject3).invokeBasic(i);
  }
  
  static void dummy()
  {
    "BMH.reinvoke_002=Lambda(a0:L/SpeciesData,a1:I)=>{\n    t2:L=BoundMethodHandle$Species_L3.argL1(a0:L);\n    t3:L=BoundMethodHandle$Species_L3.argL0(a0:L);\n    t4:I=MethodHandle.invokeBasic(t3:L,t2:L,a1:I);\n    t5:L=BoundMethodHandle$Species_L3.argL2(a0:L);\n    t6:D=MethodHandle.invokeBasic(t5:L,t4:I);t6:D}";
  }
}

LambdaForm$DMH006文件:

final class LambdaForm$DMH006
{
  @LambdaForm.Hidden
  @LambdaForm.Compiled
  @ForceInline
  static int invokeVirtual_001_LI_I(Object paramObject1, Object paramObject2, int paramInt)
  {
    Object localObject = DirectMethodHandle.internalMemberName(paramObject1);
    return MethodHandle.linkToVirtual(paramObject2, paramInt, (MemberName)localObject);
  }
  
  static void dummy()
  {
    "DMH.invokeVirtual_001_LI_I=Lambda(a0:L,a1:L,a2:I)=>{\n    t3:L=DirectMethodHandle.internalMemberName(a0:L);\n    t4:I=MethodHandle.linkToVirtual(a1:L,a2:I,t3:L);t4:I}";
  }
}

2 Invokers.checkGenericType

2.1 invokeExact进行严格匹配检查

invokeExact会确认该invokevirtual指令对应的方法描述符和该MethodHandle类型是否严格匹配,不匹配会抛出异常。

double resultE = (double)mh.invokeExact(1);

会进入如下方法进行检查:

    @ForceInline
    void checkExactType(Object mhObj, Object expectedObj) {
        MethodHandle mh = (MethodHandle) mhObj;
        MethodType expected = (MethodType) expectedObj;
        MethodType actual = mh.type();
        if (actual != expected)
            throw newWrongMethodTypeException(expected, actual);
    }

这里的mhObj就是当前的MethodHandle:




这里的expectedObj就是从实际的参数和返回类型派生符号类型描述符,也就是invokevirtual指令对应的方法描述符:



这里会判断mhObj.type()与expectedObj是否相等,如果不等直接抛出异常newWrongMethodTypeException:
Exception in thread "main" java.lang.invoke.WrongMethodTypeException: expected (int)int but found (int)double
    at java.lang.invoke.Invokers.newWrongMethodTypeException(Invokers.java:298)
    at java.lang.invoke.Invokers.checkExactType(Invokers.java:309)
    at com.enjoy.learn.core.oop.method.PolymorphicSignatureTest.main(PolymorphicSignatureTest.java:33)

1.2.2 invoke自动适配参数类型

(R)MH.invoke(a*) => MH.asType(TYPEOF(a*:R)).invokeBasic(a*)}

double result2 = (double)mh.invoke(1);

进入如下代码:

    /** Static definition of MethodHandle.invokeGeneric checking code.
     * Directly returns the type-adjusted MH to invoke, as follows:
     * {@code (R)MH.invoke(a*) => MH.asType(TYPEOF(a*:R)).invokeBasic(a*)}
     */
    /*non-public*/ static
    @ForceInline
    Object checkGenericType(Object mhObj, Object expectedObj) {
        MethodHandle mh = (MethodHandle) mhObj;
        MethodType expected = (MethodType) expectedObj;
        return mh.asType(expected);
        /* Maybe add more paths here.  Possible optimizations:
         * for (R)MH.invoke(a*),
         * let MT0 = TYPEOF(a*:R), MT1 = MH.type
         *
         * if MT0==MT1 or MT1 can be safely called by MT0
         *  => MH.invokeBasic(a*)
         * if MT1 can be safely called by MT0[R := Object]
         *  => MH.invokeBasic(a*) & checkcast(R)
         * if MT1 can be safely called by MT0[* := Object]
         *  => checkcast(A)* & MH.invokeBasic(a*) & checkcast(R)
         * if a big adapter BA can be pulled out of (MT0,MT1)
         *  => BA.invokeBasic(MT0,MH,a*)
         * if a local adapter LA can cached on static CS0 = new GICS(MT0)
         *  => CS0.LA.invokeBasic(MH,a*)
         * else
         *  => MH.asType(MT0).invokeBasic(A*)
         */
    }
    public MethodHandle asType(MethodType newType) {
        // Fast path alternative to a heavyweight {@code asType} call.
        // Return 'this' if the conversion will be a no-op.
        if (newType == type) {
            return this;
        }
        // Return 'this.asTypeCache' if the conversion is already memoized.
        MethodHandle atc = asTypeCached(newType);
        if (atc != null) {
            return atc;
        }
        return asTypeUncached(newType);
    }

asType方法可能会抛出NullPointerException(newType是null引用)或者WrongMethodTypeException(如果类型转换没法进行)。

MethodHandle.asType会返回一个适配器MethodHandle将现有的MethodHandle适配成目标类型newType。
新的适配器MethodHandle调用invoke时:
1)将入参列表进行转换以适配老的MethodHandle的参数列表
2)以转换后的参数列表调用老的MethodHandle
3)将老的MethodHandle的返回值转换为新的适配器MethodHandle的返回类型

3 Invokers.checkCustomized

    /*non-public*/ static
    @ForceInline
    void checkCustomized(Object o) {
        MethodHandle mh = (MethodHandle)o;
        if (mh.form.customized == null) {
            maybeCustomize(mh);
        }
    }

    /*non-public*/ static
    @DontInline
    void maybeCustomize(MethodHandle mh) {
        byte count = mh.customizationCount;
        if (count >= CUSTOMIZE_THRESHOLD) {
            mh.customize();
        } else {
            mh.customizationCount = (byte)(count+1);
        }
    }

CUSTOMIZE_THRESHOLD的值为127。当调用次数超过127时,调用MethodHandle.customize()为该MethodHandle定制一个LambdaForm,并将该MH的(final LambdaForm form)设置为新的LambdaForm。

    /** Craft a LambdaForm customized for this particular MethodHandle */
    /*non-public*/
    void customize() {
        if (form.customized == null) {
            LambdaForm newForm = form.customize(this);
            updateForm(newForm);
        } else {
            assert(form.customized == this);
        }
    }

4.BoundMethodHandle 适配器

4.1 调用栈

LambdaForm$BMH002文件:

final class LambdaForm$BMH002
{
  @LambdaForm.Hidden
  @LambdaForm.Compiled
  @ForceInline
  static double reinvoke_002(Object paramObject, int paramInt)
  {
    Object localObject1 = (paramObject = (BoundMethodHandle.Species_L3)paramObject).argL1;
    Object localObject2 = ((BoundMethodHandle.Species_L3)paramObject).argL0;
    int i = ((MethodHandle)localObject2).invokeBasic(localObject1, paramInt);
    Object localObject3 = ((BoundMethodHandle.Species_L3)paramObject).argL2;
    return ((MethodHandle)localObject3).invokeBasic(i);
  }
  
  static void dummy()
  {
    "BMH.reinvoke_002=Lambda(a0:L/SpeciesData,a1:I)=>{\n    t2:L=BoundMethodHandle$Species_L3.argL1(a0:L);\n    t3:L=BoundMethodHandle$Species_L3.argL0(a0:L);\n    t4:I=MethodHandle.invokeBasic(t3:L,t2:L,a1:I);\n    t5:L=BoundMethodHandle$Species_L3.argL2(a0:L);\n    t6:D=MethodHandle.invokeBasic(t5:L,t4:I);t6:D}";
  }
}

4.2 适配器BoundMethodHandle$Species_L3各参数值

BMH的注释:

/**
 * The flavor of method handle which emulates an invoke instruction
 * on a predetermined argument.  The JVM dispatches to the correct method
 * when the handle is created, not when it is invoked.
 *
 * All bound arguments are encapsulated in dedicated species.
 */
/*non-public*/ abstract class BoundMethodHandle extends MethodHandle {

BMH模拟对预先确定参数的调用指令,JVM在创建MH时就已经确定了调度的方法,而不是调用时。所有绑定参数都封装在专用的species中。

如下为BoundMethodHandle$Species_L3文件:

final class BoundMethodHandle$Species_L3
  extends BoundMethodHandle
{
  @Stable
  static BoundMethodHandle.SpeciesData SPECIES_DATA;
  final Object argL0;
  final Object argL1;
  final Object argL2;
  
  private BoundMethodHandle$Species_L3(MethodType paramMethodType, LambdaForm paramLambdaForm, Object paramObject1, Object paramObject2, Object paramObject3)
  {
    super(paramMethodType, paramLambdaForm);
    this.argL0 = paramObject1;
    this.argL1 = paramObject2;
    this.argL2 = paramObject3;
  }
  
  final BoundMethodHandle.SpeciesData speciesData()
  {
    return SPECIES_DATA;
  }
  
  final int fieldCount()
  {
    return 3;
  }
  
  static BoundMethodHandle make(MethodType paramMethodType, LambdaForm paramLambdaForm, Object paramObject1, Object paramObject2, Object paramObject3)
  {
    return new Species_L3(paramMethodType, paramLambdaForm, paramObject1, paramObject2, paramObject3);
  }
  
  final BoundMethodHandle copyWith(MethodType paramMethodType, LambdaForm paramLambdaForm)
  {
    return new Species_L3(paramMethodType, paramLambdaForm, this.argL0, this.argL1, this.argL2);
  }
  
  final BoundMethodHandle copyWithExtendL(MethodType paramMethodType, LambdaForm paramLambdaForm, Object paramObject)
    throws Throwable
  {
    return SPECIES_DATA.extendWith((byte)0).constructor().invokeBasic(paramMethodType, paramLambdaForm, this.argL0, this.argL1, this.argL2, paramObject);
  }
  
  final BoundMethodHandle copyWithExtendI(MethodType paramMethodType, LambdaForm paramLambdaForm, int paramInt)
    throws Throwable
  {
    return SPECIES_DATA.extendWith((byte)1).constructor().invokeBasic(paramMethodType, paramLambdaForm, this.argL0, this.argL1, this.argL2, paramInt);
  }
  
  final BoundMethodHandle copyWithExtendJ(MethodType paramMethodType, LambdaForm paramLambdaForm, long paramLong)
    throws Throwable
  {
    return SPECIES_DATA.extendWith((byte)2).constructor().invokeBasic(paramMethodType, paramLambdaForm, this.argL0, this.argL1, this.argL2, paramLong);
  }
  
  final BoundMethodHandle copyWithExtendF(MethodType paramMethodType, LambdaForm paramLambdaForm, float paramFloat)
    throws Throwable
  {
    return SPECIES_DATA.extendWith((byte)3).constructor().invokeBasic(paramMethodType, paramLambdaForm, this.argL0, this.argL1, this.argL2, paramFloat);
  }
  
  final BoundMethodHandle copyWithExtendD(MethodType paramMethodType, LambdaForm paramLambdaForm, double paramDouble)
    throws Throwable
  {
    return SPECIES_DATA.extendWith((byte)4).constructor().invokeBasic(paramMethodType, paramLambdaForm, this.argL0, this.argL1, this.argL2, paramDouble);
  }
}

调试方法:
在运行到checkGenericType中,在BMH的构造函数处打断点;

    /*non-public*/ BoundMethodHandle(MethodType type, LambdaForm form) {
        super(type, form);
        assert(speciesData() == speciesData(form));
    }

然后获得如下调用栈:




分析这五个参数:
param_1是方法描述符为"(I)D"的MethodType,代表根据实际类型生成的方法描述符。



param_2是LambdaFrom

param_3是之前lookup()生成MH,代表原始的MH:

1)其MemberName member代表对指定类PolymorphicSinatureTest的方法calculate:(I)I的引用
2)其MethodType type就是对方法类型的描述(返回类型int;入参(1-PolymorphicSinatureTest,2-int))
3)其LambdaForm form值如下

DMH.invokeVirtual_001_LI_I=Lambda(a0:L,a1:L,a2:I)=>{
    t3:L=DirectMethodHandle.internalMemberName(a0:L);
    t4:I=MethodHandle.linkToVirtual(a1:L,a2:I,t3:L);t4:I}

param_4是之前传入的入参bindTo(new PolymorphicSignatureTest())



param_5是调用完老的MH后,需要调用该方法进行返回值转换


因此可知BMH的各参数值如下:
MethodType type = "(I)D"的MethodType
LambdaForm form = LambdaForm$BMH002.reinvoke_002
argL0 = 代表原始的MH
argL1 = 之前传入的入参bindTo(new PolymorphicSignatureTest())
argL2 = DMH intToDouble (调用完老的MH后,需要调用该方法进行返回值转换)

4.3 理解 LambdaForm$BMH002.reinvoke_002方法

  static double reinvoke_002(Object paramObject, int paramInt)
  {
    Object localObject1 = (paramObject = (BoundMethodHandle.Species_L3)paramObject).argL1;
    Object localObject2 = ((BoundMethodHandle.Species_L3)paramObject).argL0;
    int i = ((MethodHandle)localObject2).invokeBasic(localObject1, paramInt);
    Object localObject3 = ((BoundMethodHandle.Species_L3)paramObject).argL2;
    return ((MethodHandle)localObject3).invokeBasic(i);
  }

两个入参的含义:
1)paramObject 为上面介绍的适配器BMH
2)paramInt 实际传入的参数值:(double)mh.invoke(1)中的1

Object localObject1 = (paramObject = (BoundMethodHandle.Species_L3)paramObject).argL1;
将入参bindTo(new PolymorphicSignatureTest())赋值给localObject1

Object localObject2 = ((BoundMethodHandle.Species_L3)paramObject).argL0;
将原始MH赋值给localObject2

int i = ((MethodHandle)localObject2).invokeBasic(localObject1, paramInt);
通过原始MH调用invokeBasic(new PolymorphicSignatureTest(), 1)调用实际的方法,获得int类型的返回值i

Object localObject3 = ((BoundMethodHandle.Species_L3)paramObject).argL2;
将DMH intToDouble赋值给localObject3

((MethodHandle)localObject3).invokeBasic(i)
调用DMH intToDouble,将int类型转为double类型并返回

总结:
适配器MethodHandle调用invoke时:
1)将入参列表进行转换以适配老的MethodHandle的参数列表
2)以转换后的参数列表调用老的MethodHandle
3)将老的MethodHandle的返回值转换为新的适配器MethodHandle的返回类型

5.原始DMH.invokeBasic(new PolymorphicSignatureTest(), 1)

根据栈信息该方法会调用:
java.lang.invoke.LambdaForm$DMH006/2055281021.invokeVirtual_001_LI_I(LambdaForm$DMH006:1000011)
该方法本身就是原始DMH的form,请参考上一节的param_3的LambdaForm form值。

final class LambdaForm$DMH006
{
  @LambdaForm.Hidden
  @LambdaForm.Compiled
  @ForceInline
  static int invokeVirtual_001_LI_I(Object paramObject1, Object paramObject2, int paramInt)
  {
    Object localObject = DirectMethodHandle.internalMemberName(paramObject1);
    return MethodHandle.linkToVirtual(paramObject2, paramInt, (MemberName)localObject);
  }
  
  static void dummy()
  {
    "DMH.invokeVirtual_001_LI_I=Lambda(a0:L,a1:L,a2:I)=>{\n    t3:L=DirectMethodHandle.internalMemberName(a0:L);\n    t4:I=MethodHandle.linkToVirtual(a1:L,a2:I,t3:L);t4:I}";
  }
}

根据该方法的含义,可推知invokeVirtual_001_LI_I三个参数的含义:
paramObject1 —— 原始DMH
paramObject2 —— new PolymorphicSignatureTest()
paramInt —— 1

Object localObject = DirectMethodHandle.internalMemberName(paramObject1);
获取原始DMH的member,也即类PolymorphicSinatureTest的方法calculate:(I)I的引用。

    /*non-public*/ static Object internalMemberNameEnsureInit(Object mh) {
        DirectMethodHandle dmh = (DirectMethodHandle)mh;
        dmh.ensureInitialized();
        return dmh.member;
    }

MethodHandle.linkToVirtual(paramObject2, paramInt, (MemberName)localObject);
该方法最后一个参数必须是MemberName类型,也即将参数传入PolymorphicSinatureTest的方法calculate:(I)I,进行调用。

    /**
     * Private method for trusted invocation of a MemberName of kind {@code REF_invokeVirtual}.
     * The caller signature is restricted to basic types as with {@code invokeBasic}.
     * The trailing (not leading) argument must be a MemberName.
     * @param args the signature-polymorphic parameter list, statically represented using varargs
     * @return the signature-polymorphic result, statically represented using {@code Object}
     */
    /*non-public*/ static native @PolymorphicSignature Object linkToVirtual(Object... args) throws Throwable;

你可能感兴趣的:(方法调用8——MethodHandle方法调用实现原理)