程序问答   发布时间:2022-06-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了对象的InvokeExact,其类型由类加载器动态加载大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决对象的InvokeExact,其类型由类加载器动态加载?

开发过程中遇到对象的InvokeExact,其类型由类加载器动态加载的问题如何解决?下面主要结合日常开发的经验,给出你关于对象的InvokeExact,其类型由类加载器动态加载的解决方法建议,希望对你解决对象的InvokeExact,其类型由类加载器动态加载有所启发或帮助;

invokeExact如果参数的编译时类型与的参数类型不匹配,则无法使用@H_65_3@methodHandle。像cast在上调用那样的Generic构造并没有帮助,Class<T>编译器仍然不知道动态类型。

或者,换句话说,由于类型擦除,的类型tObjObject处于字节码级别。这是的“调用类型” @H_65_3@methodHandle。

最简单的解决方案是使用invoke而不是invokeExact

如果要使用invokeExact,您唯一可以做的就是将转换为@H_65_3@methodHandle最终将要调用的类型,即将第一个参数的类型更改为Object

@H_65_3@mymH=mymH.asType(mymH.type().changeParameterType(0, Object.class));
// Now it doesn’t matter that obj has compile-time type Object
assertEquals((int)R_750_11845@ymH.invokeExact(obj, "addintaasdsa", 10, 20.0f), 12);

解决方法

我整天都在这个问题上。我的问题是如何在实例上进行MethodHandle.invokeExact调用,该实例的类类型在程序运行时动态加载。为了使问题更清楚,我在下面显示我的示例代码:

Class<?> expClass = new MyClassLoader().load(....)

//expClass is AddSample.class which is subclass of BaseTemplate         
 BaseTemplate obj = expClass.getConstructor(...)
                .newInstance(...);
MethodHandle mymH = MethodHandles.lookup().findVirtual(expClass,methodName,..);
System.out.println("Object type "+obj.getClass()); //Print addSample

// If obj is declared as "AddSample obj",the runtime would be OK.
assertEquals((int)R_750_11845@ymH.invokeExact(obj,"addintaasdsa",10,20.0f),12);

在此示例中,expClass是动态加载的,其类类型为AddSample。下一行的obj实例被声明为BaseTemplate,其真实类型为AddSample。类AddSample是BaseTemplate的子类。然后,向其添加函数创建了一个MethodHandle
mymh,AddSample但是由于接收器类型不匹配,无法调用mymH。

该@H_65_3@mymH.invokeExact加薪运行时错误

java.lang.invoke.WrongMethodTypeException: expected (AddSample,String,int,float)int but found (Object,float)int

因为此对象的接收者@H_65_3@mymH声明为在expClass(AddSample)上,但是obj提供的接收者当前被声明为BaseTemaplte,尽管obj的Class为AddSample。InvokeExact需要精确的参数匹配。


我的问题可能简化为:如何将实例从其基本类型转换为动态加载的子类型?

BaseTemplate obj = ...
Class<?> newtype = class('AddSample') //dynamic loaded...

将obj的声明类型更改为动态加载的AddSample。

updatE:

Class<T> expClass = (Class<T>) new MyClassLoader().run(className,b);
BaseTemplate obj = ..
Class<T> newType = (Class<T>) obj.getClass().getClassLoader().loadClass("AddSample");
T tObj = newType.cast(obj);
assertEquals((int)R_750_11845@ymH.invokeExact(tObj,12);

使用强制转换并不能帮助解决与以前的结果相同的问题。原因仍然是给定的参数与mymH声明不完全匹配。当我检查生成的字节码时,它将更加清楚:

L23  # For cast 
    LINEnumbER 126 L23
    ALOAD 10: newType
    ALOAD 8: obj
    INVOKEVIRTUAL Class.cast (Object) : Object  #tObj is Object and its real type is AddSample here
    ASTORE 11
   L24
    LINEnumbER 128 L24
    ALOAD 9: mymH           # Push mymH to stack
    ALOAD 11: tObj          # Push tObj to Stack. tObj is declared Object type and its real type is AddSample. 
    LDC "addintaasdsa"      #Push String to Stack
    BIPUSH 10               #Push int to Stacl
    LDC 20.0                #Push float to Stack 
    INVOKEVIRTUAL MethodHandle.invokeExact (Object,float) : int
@H_793_2@mymH指向 (AddSample,float)int,但是给定参数: (Object,float),这会导致运行时错误,如我先前所示。

谢谢

大佬总结

以上是大佬教程为你收集整理的对象的InvokeExact,其类型由类加载器动态加载全部内容,希望文章能够帮你解决对象的InvokeExact,其类型由类加载器动态加载所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。