大佬教程收集整理的这篇文章主要介绍了对象的InvokeExact,其类型由类加载器动态加载,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
invokeExact
如果参数的编译时类型与的参数类型不匹配,则无法使用@H_65_3@methodHandle。像cast
在上调用那样的Generic构造并没有帮助,Class<T>
编译器仍然不知道动态类型。
或者,换句话说,由于类型擦除,的类型tObj
仍Object
处于字节码级别。这是的“调用类型” @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...
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,请注明来意。