Open kriegaex opened 4 years ago
The VerifyError
is a bug and I think I already understood it and have a fix ready. I will look into further optimizing the stack map frame; if a constructor has no branch after the super method call, currently the unitializedThis frame is not corrected to initialized state.
The easy solution is to always require a full frame but I'd like to explore the option to detect if a frame correction was applied and to only require the full frame in case of it.
The bug should be fixed by https://github.com/raphw/byte-buddy/commit/3fb9bbb85e7fe3af2d631d41df71f905b90577b3 - can you validate that this patch works for you by building master yourself?
Whoa, you caught me on the wrong foot here. I don't know nearly enough about the inner workings of classes and methods on the level of stack frames. But I am confident the fix is good. Gonna check it out soon and give feedback here.
I can confirm that the VerifyError
is still reproducible in 1.10.10 but gone with the latest 1.10.11-SNAPSHOT. Thanks for the swift reaction. :-)
Any thought about my requests to handle superfluous annotations or annotation parameters gracefully, continuing with the rest which is applicable? Or what about making it configurable that processing continues? By now my work has progressed and I have separated my generic wrapper advice pairs for
Especially the latter are very limited in what you can do other than suppress the type initialiser, but there still is a lot of very similar (next to duplicate) code between method and constructor advice pairs.
I think these issues are fixed, closing the ticket for it.
Hm, actually no, at least you never mentioned anything about it. I am referring to https://github.com/raphw/byte-buddy/issues/857#issuecomment-625846289 and BB handling unexpected annotations gracefully, allowing the user to have one advice pair for different types of targets (methods, constructors, static type initialisers). If you close as "won't fix", then of course the status of this ticket is correct.
There's been a ticket to support the feature you're wanting for a while, the verification error is adressed.
I cannot find the corresponding ticket. Maybe we are talking about different things. Would you mind pointing me to the ticket you mean? Then I can verify if it is what I mean. Thank you.
Isn't this what you were looking for? https://github.com/raphw/byte-buddy/issues/375
No, that is something very specific and completely different. I am talking about this part of my initial message here:
I was expecting ByteBuddy to handle cases where some (combinations of) annotations are unsupported gracefully, i.e. just ignore them and maybe log a warning, similar to how
@Advice.This
is just set to null for static methods or constructors when before entering them. Unfortunately my expectation was not met.
And then in https://github.com/raphw/byte-buddy/issues/857#issuecomment-625846289 I also said:
Any thought about my requests to handle superfluous annotations or annotation parameters gracefully, continuing with the rest which is applicable? Or what about making it configurable that processing continues? By now my work has progressed and I have separated my generic wrapper advice pairs for
- methods (both static and non-static),
- constructors,
- static type initialisers.
Especially the latter are very limited in what you can do other than suppress the type initialiser, but there still is a lot of very similar (next to duplicate) code between method and constructor advice pairs.
Please feel free to ask follow-up questions or to contact me via Gitter if my explanation is unclear.
Of course, this makes sense. It would probably be possible to add a property like ignoreUnsupported = true
to allow for such overrides. This makes sense; if I find the time, I might add it.
Situation: I am writing a generic advice which works fine for all kinds of methods, even decorating already loaded JRE classes work fine. Now I want to extend it from
@Origin Method method
to@Origin Executable method
in order to cover constructors, too. Later I might want to extend it to initialisers, but I have not looked into that yet. Unfortunately neither the manual nor the Javadoc explain much there, so I need to experiment.I was expecting ByteBuddy to handle cases where some (combinations of) annotations are unsupported gracefully, i.e. just ignore them and maybe log a warning, similar to how
@Advice.This
is just set tonull
for static methods or constructors when before entering them. Unfortunately my expectation was not met. But let me not get ahead of myself and show you some code first:Target class:
Driver application advising target class:
Advice implementations:
First let me comment out some problematic stuff in order to start with a running before/after advice pair:
Console log:
So far, so good. Now let me start to modify the advice code a bit:
Activating this line in the exit advice
yields
Is catching exceptions for constructors unsupported? The Javadoc of
@Advice.Thrown
does not mention anything like it.Secondly, if it is unsupported couldn't this just be logged as a warning and
throwable
always set tonull
? Plus documentation and a comprehensible error message, of course. Now the whole advice does not work.Anyway, let's activate the corresponding part of the
OnMethodExit
annotation too:This yields:
Okay, now the error message makes more sense. I seem to use an unsupported feature. But again, can ByteBuddy not handle this gracefully and just warn about it and ignore what it cannot use? I know, I could just write a very similar advice pair to the one covering methods for constructors, but I want to avoid it not just for reasons of unwanted code duplication but also for others I do not want to bother you with.
Okay, let me comment out the two exception handling parts in the exit advice again and try this:
This yields:
Same request: Can I just get a warning instead and let ByteBuddy continue working? Maybe there is a configuration setting to allow for softening advice wiring exceptions to warnings and I am unaware of it. If not, maybe an optional parameter for
OnMethodEnter
andOnMethodExit
could be introduced so as not to break backward compatibility for developers expecting exceptions but an option to make ByteBuddy behave differently.BTW, of course
Cannot skip code execution from constructor
makes sense to me. I cannot just skip a constructor without throwing an exception or causing one. But as a feature I would like to be able to skip indeed and make the method return another compatible object instead. This would be nice in a mocking advice. One way to do that would be to actively assign a value to a@This
parameter in the enter advice. Besides, this "exchange my object to be constructed for another one" mocking idea is one of the things I hoped to be able to implement with ByteBuddy, but there is no convenient way to do that withing the confines of my generic advice pair.Now let's use
backupArguments = false
in the exit advice. To recap, the situation with commented out stuff is:Now it gets really bad:
I do not think the
VerifyError
should occur. Is this a bug or am I doing anything wrong?I am sorry for this very wordy issue, but after thinking about it I decided not to split it into different ones, all with 99% the same code which you can just easily manipulate in order to recreate the problems.
I am working on Windows 10 with Oracle JDK 8 (sorry!) and have not tried to reproduce with more up to date JDK versions. My ByteBuddy version is 1.10.10.