-
1. Re: Rule of child class triggered for a method implemented in a parent class
ochaloup Oct 21, 2015 8:11 AM (in response to ochaloup)Hi adinn,
I'm sorry to bothering you by pushing this up just wouldn't you have some tip for me?
Or in case could you confirm that this is behavior by design and I need to apply some workaround?
Thanks a lot
ondra
-
2. Re: Rule of child class triggered for a method implemented in a parent class
adinn Oct 21, 2015 9:54 AM (in response to ochaloup)Hi Ondra,
Sorry for not replying sooner -- I have been off sick for a few days.
The short answer is that this is by design -- at least according to the current design. Which means that for the moment your work-around is about as near as it is possible to get to the desired functionality.
n.b. I think you don't actually need the ^ in the CLASS clause though. If LocalConnectableXAResourceImpl inherits its commit method directly from LocalXAResourceImpl then there is no reason to inject into other subclasses of LocalXAResourceImpl. If it inherits from some intermediate class then you need to inject direct into that intermediate class and still don't need the ^.
The long answer (in case you or someone else wants to know why) is as follows:
What you are asking for is to be able to specify a rule on CLASS X METHOD m and have the Byteman agent recognise the situation where X < Y X and X inherits Y.m rather than implementing it. Byteman is only in a posiiton to recognise that there is no X.m when class X is loaded and handed over to the agent for transformation. At that point it is passed a byte[] holding the bytecode for class X and is allowed to return a modified byte[] which specifies a dfiferent version of class X.
That's all the JVMTI Java agent API allows Byteman to do. It cannot at that point transform class Y. Indeed, it cannot even rely on class Y having already been loaded. That sounds odd but transformation is triggered at class loadi time not at class resolve time. So, when a method which refers to X is resolved that will force loading and transformation of X even if Y is not yet loaded. After X has been loaded then Y will be loaded and after Y is reosolved then X will be resolved. Which means Byteman can be sure that X does not implement m but cannot be sure whether a parent class does so.
So, what if Byteman just loaded class Y itself during transformation of X. Unfortunately, this would mean that any rules defined on class Y will not be injected because the JVM will not re-enter the transformer code whne loading code from with an agent transformer. If Byteman loads classes it misses chances ot inject rules. So, Byteman does its very best to avoid loading classes during transformation. Of course, if it cannot load Y while transforming X then it cannot transform Y while transforming X.
To work around this Byteman could just note that X.m does not exist and schedule a separate thread to look up the supers chain for a target method for the rule. That would still not be good enough for several reasons.
Firstly, the transformation would not happen immediately which means Y.commit could be called on an instance of calss X before the tarnsform happened i.e. the semantics of transformation become more fuzzy.
Secondly, scheduling transformation in a separate thread is potentially slow and needs to be careful to avoid deadlocks: the dedicated thread may initiate a load while it has the transform queue locked and that load may be locked out by another thread which wants to schedule a thread for transformation.
The third problem is that the trigger code injected into Y.m needs to include a guard and skip so that the trigger region is only entered when $this is an instanxce of X. That's ok if X is visible in the classloader of Y -- you just plant the bytecode sequence aload0, instanceof "X", if_eq before the normal injected code. However, if X is not visible thne you have to plant code to obtain the classname of $this and compare it against the relevant String name for X. This is feasible but clumsy.
The fourth problem is that you have to type check the rule on the assumption that $this is an X not a Y. If X and Y are defined in different loaders then this mean using the loader of Y not X to do the checking. Byteman does not currently do that (although it is possible to make this work).
-
3. Re: Rule of child class triggered for a method implemented in a parent class
ochaloup Oct 21, 2015 10:05 AM (in response to adinn)I see. Thanks for the explanation.
I really appreciate your "answer kind of articles" in any of your replies. It's really nice way how to understand how the things work. Thanks again for it!