noob question: add behavior to a method

218 views
Skip to first unread message

Piotr Morgwai Kotarbinski

unread,
Apr 6, 2021, 9:09:55 AM4/6/21
to Byte Buddy
Hi all,
I'm new to byte-buddy, so it's probably a very noob question:
Given Sample.someMethod(...) and InvocationHandler decoration, I want to create a dynamic subclass that overrides someMethod with
someMethod(...) {
    decoration.invoke(...);
    super.someMethod(...);
}

My code looks like this:

Class<? extends Sample> dynamicSubclass = new ByteBuddy()
    .subclass(Sample.class)
    .method(ElementMatchers.named("someMethod"))
        .intercept(new Implementation.Compound(
            InvocationHandlerAdapter.of(decoration),
            SuperMethodCall.INSTANCE))
    .make()
    .load(Sample.class.getClassLoader())  // line 42 throws the below exception
    .getLoaded();

...and it results in the following exception:

java.lang.VerifyError: Expecting a stack map frame
Exception Details:
Location: pl/morgwai/sample/pojo/ByteBuddySample$Sample$ByteBuddy$PXUw8Sz7.someMethod(I)Ljava/lang/String; @27: aload_0 
Reason: Error exists in the bytecode
Bytecode:
0000000: b200 0a2a b200 0e04 bd00 1059 031b b800
0000010: 1653 b900 1c04 00c0 001e b02a 1bb7 0020
0000020: b0
at java.base/java.lang.Class.getDeclaredFields0(Native Method)
at java.base/java.lang.Class.privateGetDeclaredFields(Class.java:3061) 
at java.base/java.lang.Class.getDeclaredField(Class.java:2409) 
at net.bytebuddy.implementation.LoadedTypeInitializer$ForStaticField.onLoad(LoadedTypeInitializer.java:122)
at net.bytebuddy.implementation.LoadedTypeInitializer$Compound.onLoad(LoadedTypeInitializer.java:192)
at net.bytebuddy.dynamic.TypeResolutionStrategy$Passive.initialize(TypeResolutionStrategy.java:102)
at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:6292)
at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:6281) at pl.morgwai.sample.pojo.ByteBuddySample.main(ByteBuddySample.java:42)

:(

I've asked already on SO (https://stackoverflow.com/questions/66967504/add-behavior-to-method-with-bytebuddy) but someone downvoted it (without explanation), so the visibility is decreased, hence I'm trying my luck on this mailing list.

I've noticed that I can achieve for example just
someMethod(...) {
    decoration.invoke(...);
}
by doing  .intercept(InvocationHandlerAdapter.of(decoration))
so it seems I'm not using Implementation.Compound properly...

I was also able to get
someMethod(...) {
    super.someMethod(...);
    decoration.invoke(...);
}
by doing
.intercept(SuperMethodCall.INSTANCE.andThen(
        InvocationHandlerAdapter.of(decoration)))
but I can't do the other way around to achieve the order I need as InvocationHandlerAdapter does not implement Implementation.Composable...

Any help will be highly appreciated :)

Thanks!

Rafael Winterhalter

unread,
Apr 6, 2021, 2:39:23 PM4/6/21
to Piotr Morgwai Kotarbinski, Byte Buddy
The invocation handler adapter does not currently implement Implementation.Composable interface. The verifier error comes from both implementations returning, the adapter must therefore be made aware of the dropping. I just added the interface on master, it's missing from an oversight.

Would using MethodDelegation be an alternative? It's normally more efficient to begin with and you can call MethodCall.to(...).andThen(...)

--
You received this message because you are subscribed to the Google Groups "Byte Buddy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to byte-buddy+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/byte-buddy/96646d1c-36e3-4ae1-84e8-327f3701e4aan%40googlegroups.com.

Piotr Morgwai Kotarbinski

unread,
Apr 6, 2021, 3:28:40 PM4/6/21
to Byte Buddy
On Wednesday, April 7, 2021 at 1:39:23 AM UTC+7 rafae...@gmail.com wrote:
The invocation handler adapter does not currently implement Implementation.Composable interface. The verifier error comes from both implementations returning, the adapter must therefore be made aware of the dropping. I just added the interface on master, it's missing from an oversight.


does it mean that I can expect that in the next release InvocationHandler will be implementing  Composable ?
 

Would using MethodDelegation be an alternative? It's normally more efficient to begin with and you can call MethodCall.to(...).andThen(...)


 I guess no (but please correct me if I'm wrong) as actually I don't know the method signature: in the example above for simplicity I wrote

    .subclass(Sample.class)
    .method(ElementMatchers.named("someMethod"))

but in fact the class comes as a parameter to my function and I lookup for methods by their annotations and they may have different set of parameters each time:

public <T> Class<? extends T> decorate(Class<T> baseClass, Class<? extends Annotation> annotationType) {
    Class<? extends T> dynamicSubclass = new ByteBuddy()
    .subclass(baseClass)
    .method(ElementMatchers.isAnnotatedWith(annotationType))
    ...

So as far as I understand, I cannot use MethodDelegation as the target needs to have an existing method with matching signature (which I cannot predict), correct?

Many many thanks!

Rafael Winterhalter

unread,
Apr 6, 2021, 3:40:54 PM4/6/21
to Piotr Morgwai Kotarbinski, Byte Buddy
MethodDelegation allows you to delegate to any method, it could even have the same signature as the invocation handler method, but it requires annotations on each parameter:

public class Foo {
  public static void hello() { System.out.prinltn("hello"); }
}

would work for any method passed to it. You can of course wait for the next release or use JitPack to use the current master, the changes are already pushed.

--
You received this message because you are subscribed to the Google Groups "Byte Buddy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to byte-buddy+...@googlegroups.com.

Piotr Morgwai Kotarbinski

unread,
Apr 6, 2021, 4:40:43 PM4/6/21
to Byte Buddy
I've just tried the version built from the master and it works great!  i'll stick with it and will be waiting for the official release :)

Many thanks again!

Reply all
Reply to author
Forward
0 new messages