当我尝试执行以下操作时,在加载调用中出现异常:
Field datasourceExtensionField = Grid.class.getDeclaredField("datasourceExtension");
datasourceExtensionField.setAccessible(true);
RpcDataProviderExtension rpcDataProviderExtension = (RpcDataProviderExtension) datasourceExtensionField.get(grid);
Field activeItemHandlerField = RpcDataProviderExtension.class.getDeclaredField("activeItemHandler");
activeItemHandlerField.setAccessible(true);
Object activeItemHandler = activeItemHandlerField.get(rpcDataProviderExtension);
Field keyMapperField = activeItemHandler.getClass().getDeclaredField("keyMapper");
keyMapperField.setAccessible(true);
KeyMapper original = (KeyMapper) keyMapperField.get(activeItemHandler);
KeyMapper wrapper = new ByteBuddy() //
.subclass(KeyMapper.class) //
.defineField("original", KeyMapper.class, Visibility.PUBLIC) //
.method(ElementMatchers.any()) //
.intercept(Forwarding.toField("original")) //
.method(ElementMatchers.named("get")) //
.intercept(MethodDelegation.to(new KeyMapperWrapper(grid, original))) //
.make() //
.load(KeyMapperWrapper.class.getClassLoader()) //
.getLoaded() //
.newInstance();
// give wrapper the reference to the original
wrapper.getClass().getDeclaredField("original").set(wrapper, original);
// replace original with wrapper
keyMapperField.set(activeItemHandler, wrapper);
例外:
java.lang.VerifyError: Bad access to protected data in invokevirtual
Exception Details:
Location:
com/vaadin/server/KeyMapper$ByteBuddy$WlWljaQa.clone()Ljava/lang/Object; @4: invokevirtual
Reason:
Type 'com/vaadin/server/KeyMapper' (current frame, stack[0]) is not assignable to 'com/vaadin/server/KeyMapper$ByteBuddy$WlWljaQa'
Current Frame:
bci: @4
flags: { }
locals: { 'com/vaadin/server/KeyMapper$ByteBuddy$WlWljaQa' }
stack: { 'com/vaadin/server/KeyMapper' }
Bytecode:
0x0000000: 2ab4 000c b600 1cb0
at java.lang.Class.getDeclaredFields0(Native Method)
at java.lang.Class.privateGetDeclaredFields(Class.java:2583)
at java.lang.Class.getDeclaredField(Class.java:2068)
at net.bytebuddy.implementation.LoadedTypeInitializer$ForStaticField.onLoad(LoadedTypeInitializer.java:101)
at net.bytebuddy.implementation.LoadedTypeInitializer$Compound.onLoad(LoadedTypeInitializer.java:180)
at net.bytebuddy.dynamic.TypeResolutionStrategy$Passive.initialize(TypeResolutionStrategy.java:75)
at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:4525)
at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:4514)
at test.KeyMapperWrapper.patch(KeyMapperWrapper.java:62)
我显然不了解
Forwarding
应该如何工作,我在做什么错?我的意图是用一个代理替换现有的
KeyMapper
,在该代理中我重写一个方法,并将其余方法委托给原始方法。编辑:我现在也尝试使用
MethodDelegation
,它引发相同的异常: .method(ElementMatchers.any()) //
.intercept(MethodDelegation.to(original)) //
.method(ElementMatchers.named("get")) //
.intercept(MethodDelegation.to(new KeyMapperWrapper(grid, original))) //
最佳答案
这是Byte Buddy中的错误。但是,您尝试创建的类型不合法,Byte Buddy无法为您提供正确的错误消息。子类化时,覆盖protected
方法是合法的。但是,由于可见性的限制,在另一种类型上调用这些方法并不总是合法的。因此,在转接呼叫时,只能覆盖public
方法。您想要做的是匹配:
.method(ElementMatchers.isPublic())
该错误不再发生的地方。我已经添加了一个修复程序,可以在Byte Buddy的下一个发行版本(1.5.8)中为您提供此错误消息。