How to intercept field accesses (without getter/setter) using Bytebuddy - java

I am trying to use bytebuddy to intercept getfield and putfield accesses. I have read the rather comprehensive documentation on the site, but from what I can understand, it covers adding getters and setters to fields, rather than intercepting field accesses.
Here is basically what I am trying to do:
...
obj.prop = value;
x = obj.prop;
...
That in both these cases, I am trying to have some method called (or some bytecode inserted) before/after the field access. I was thinking of using Advice to do it, but I am unable to find a way to have it for something other than methods.
Edit:
I am using a Java Agent to do it.
I had an idea of adding a dup to duplicate the object reference followed by the call to a static method I defined to intercept the access (I only care about the object being referred to, not the field).

There is a new component that is still under development but that is already exposed with a basic API. It is called MemberSubstitution and allows you to replace a method call or field access with another execution.
This component does however rely on replacing the code that executes an instruction. Field access is non-virtual, therefore it is not possible to create any proxy class that would intercept a virtual access. Instead, you have to redefine any existing class that reads or writes the field, for example by using a Java agent.
As for your more specific question: At the moment, there is only a 1-to-1 substitution possible. I have not yet had the time to include a mechanism for adjusting the stack and local variable sizes. Also, you would also have to dup objects lower down on the stack if the field is non-static. The problem is not trivial so to say but I hope to offer such functionality some day.
At the moment you can however replace the field access with a static method call. Possibly, you can execute the original field operation from this method.

Related

How setter methods changes business requirements?

I am working on Mockito and JUnit integration. For mocking the objects I created some setter method
#Mock
private SomeDaoImplClass someDaoImplClass
jdbcTamplate = Mockito.mock(NamedParameterJdbcTamplate.class)
someDaoImplClass.setNamedParameterJdbcTamplate(jdbcTamplate)
So method setNamedParameterJdbcTamplate(jdbcTamplate) was not there and I created this setter method in class.
I got some information that you can't create these set method in business class
b'coz its effecting business unit.
Please someone can suggest me how set methods affecting BU.
No business object should allocate its own dependencies (you know, due to that Inversion of Control/Dependency Injection thing)
So if you need to provide something to you objects you can do it either with setters or via constructor (the latter is preferred)
It's true that adding methods just for the sake of testing is a bad practice. In this case it can be even worse: adding a setter prohibit us to make the object immutable which is something desirable when working with multiple threads and adds some security restrictions (no attribute is without initialization after the constructor has finished.
If you need to add these methods document it and set its visibility to default so it's only visible from the same package (the tests will be at that same package) in order to minimize the impact in production
If you can't add a setter or modify the constructor... Well, it's not all lost. You can make use of reflection. By using this you can modify any attribute of your object even without accessors or even final attributes. Notice that this will be slower at runtime and will require some exception handling

Loading an existing java object onto stack using ASM

I am trying to use ASM for my project and hit a performance issue where I am trying to get required object using a static method and its called like 1000 times
visitor.visitMethodInsn(Opcodes.INVOKESTATIC, TrackingConstants.TO_HELPER_CLASS, "getRTTDObject",TrackingConstants.TO_HELPER_GET_CLIENT_METHOD_DESC);
visitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, TrackingConstants.CLIENT_INTERFACE_CLASS, "getPattern",TrackingConstants.CLIENT_INTERFACE_CLASS_GETPATTERN_METHOD_DESC);
This first call is causing me overhead(where I get required object and pass to next line for performing "getPattern" on the object.During investigation I realized that the object which I am trying to retrieve via the static method is available with me from the starting itself so if I was able to push that Java object onto stack and avoid the static calls I wouldn't not face any performance issues.I tried couple of ways with no luck and finally tried to create new Field of the object but get an IllegalArgumentException similar to this post
Creating a new field with asm 4 after going through the link I realized that we need write code to create the object and can't directly use existing object.
So is there no way I can load my existing Java object onto stack (I guess it will already be on stack, is there a way I can use it) and perform required operations instead of using Static call to get it? Is there a way I can achieve it?
Once the object is on the stack (presumably after you call your static method the first time), you can:
Emit a DUP instruction to duplicate the value already on the stack each time it is needed. This is probably the most performant option, but it requires you to craft your bytecode in such a way that the value will always be at/near the top of the stack when you need it. There are a few variants of the DUP instruction to choose from, each with different behavior; see the JVM Specification ยง6.5 for details.
Call the static method once, then store the result in a temporary variable (use one of the ASTORE instruction variants). Push it onto the stack when it's needed by using the corresponding ALOAD variant.
Depending on the structure of your method, you may also combine these techniques (load from a temporary local, DUP as necessary, do something unrelated, repeat, etc.).

Adding a field to Java class

Looked at using CGLib, ASM, BCEL (aspect) and Javassist to add a field to a class during runtime....
Just to get my head straight it looks like these bytecode manipulators don't update the actual class rather allow the user to only dump the modification (like with CGLib and the writeFile method). Was hoping I would find a solution that (a) loaded the class (rather than doing an InputStream with BCEL) and (b) updated the class.
Maybe this is normal? Do people usually create a proxy and pass the proxy around?
What I want to do is to add a field (note: not a property via get/set methods) before passing the object along to a framework that looks for fields (not properties) with a particular annotation. So "clients" are creating my target classes that I want to inject with an extra field. Intercepting with AOP calls to a service layer where I want to manipulate these objects.
You can redefine classes with Intrumentation. However a common limiation is that you cannot change the fields used. This is because you cannot change the contents of a object (or add to it) once it has been created.
In your case you can,
create a proxy as you suggest, however proxies need to be interfaces.
create a subclass which has the additional field(s)
add the field before the class has loaded.

Accessing fields from a proxied object

I've run into an interesting problem while developing an ORM framework for Android. I'm using a library called dexmaker for bytecode manipulation, which enables me to create proxies for persistent objects in order to implement lazy loading.
The proxied instance has an associated InvocationHandler such that when a method is called on the proxy, the invoke method is called on the InvocationHandler, which then calls the proxied object's respective method assuming it's been lazily loaded. Nothing too surprising -- it's just like Java's Proxy class but allows me to proxy actual classes instead of interfaces (see dexmaker's ProxyBuilder).
The part that's become problematic is that I also use reflection to retrieve field values from persistent objects and -- now that I've introduced lazy loading -- proxies. Here is what I'm currently doing:
for (Field f : getPersistentFields(model.getClass()) {
...
Object val = f.get(model); // model is either a persistent object or a proxy for one
mapField(f, val, map);
}
This of course works for regular model instances, but for proxied instances, f.get(model) is not retrieving the proxied object's field value. Instead, it's returning the default value assigned in the class's constructor. The access on the proxy's field is not being intercepted obviously.
My question is this: is there any way I can intercept an access on a proxy's member variable made through reflection? If not, how can I retrieve the value of a proxy's field in a "reflection-like" way?
One possible workaround I'm thinking of would be to retrieve and then invoke the field's getter method using reflection, but I'm wondering if there's a more direct solution. This workaround, if it actually works, would require the object to have a getter method for all persistent fields -- a requirement that should typically be followed from an OO-design point of view but also forces more work onto the user of the framework.
I'm open to any ideas.
A good solution is to access the fields using setter/getters rather than using Field class. (I believe this is more than a workaround)
On the other hand, if you want to go with the direct field accessing approach. As far as I see there is no easy way to intercept field accesses. Please check the answers to this question. Altough the question is related with intercepting field modification rather than reading
the field, it may provide some insights and direction.

In Java, how can I construct a "proxy wrapper" around an object which invokes a method upon changing a property?

I'm looking for something similar to the Proxy pattern or the Dynamic Proxy Classes, only that I don't want to intercept method calls before they are invoked on the real object, but rather I'd like to intercept properties that are being changed. I'd like the proxy to be able to represent multiple objects with different sets of properties. Something like the Proxy class in Action Script 3 would be fine.
Here's what I want to achieve in general:
I have a thread running with an object that manages a list of values (numbers, strings, objects) which were handed over by other threads in the program, so the class can take care of creating regular persistent snapshots on disk for the purpose of checkpointing the application. This persistor object manages a "dirty" flag that signifies whether the list of values has changed since the last checkpoint and needs to lock the list while it's busy writing it to disk.
The persistor and the other components identify a particular item via a common name, so that when recovering from a crash, the other components can first check if the persistor has their latest copy saved and continue working where they left off.
During normal operation, in order to work with the objects they handed over to the persistor, I want them to receive a reference to a proxy object that looks as if it were the original one, but whenever they change some value on it, the persistor notices and acts accordingly, for example by marking the item or the list as dirty before actually setting the real value.
Edit: Alternatively, are there generic setters (like in PHP 5) in Java, that is, a method that gets called if a property doesn't exist? Or is there a type of object that I can add properties to at runtime?
If with "properties" you mean JavaBean properties, i.e. represented bay a getter and/or a setter method, then you can use a dynamic proxy to intercept the set method.
If you mean instance variables, then no can do - not on the Java level. Perhaps something could be done by manipulations on the byte code level though.
Actually, the easiest way to do it is probably by using AspectJ and defining a set() pointcut (which will intercept the field access on the byte code level).
The design pattern you are looking for is: Differential Execution. I do believe.
How does differential execution work?
Is a question I answered that deals with this.
However, may I suggest that you use a callback instead? You will have to read about this, but the general idea is that you can implement interfaces (often called listeners) that active upon "something interesting" happening. Such as having a data structure be changed.
Obligitory links:
Wiki Differential execution
Wiki Callback
Alright, here is the answer as I see it. Differential Execution is O(N) time. This is really reasonable, but if that doesn't work for ya Callbacks will. Callbacks basically work by passing a method by parameter to your class that is changing the array. This method will take the value changed and the location of the item, pass it back by parameter to the "storage class" and change the value approipriately. So, yes, you have to back each change with a method call.
I realize now this is not what you want. What it appears that you want is a way that you can supply some kind of listener on each variable in an array that would be called when that item is changed. The listener would then change the corresponding array in your "backup" to refect this change.
Natively I can't think of a way to do this. You can, of course, create your own listeners and events, using an interface. This is basically the same idea as the callbacks, though nicer to look at.
Then there is reflection... Java has reflection, and I am positive you can write something using it to do this. However, reflection is notoriously slow. Not to mention a pain to code (in my opinion).
Hope that helps...
I don't want to intercept method calls before they are invoked on the real object, but
rather I'd like to intercept properties that are being changed
So in fact, the objects you want to monitor are no convenient beans but a resurgence of C structs. The only way that comes to my mind to do that is with the Field Access call in JVMTI.
I wanted to do the same thing myself. My solution was to use dynamic proxy wrappers using Javassist. I would generate a class that implements the same interface as the class of my target object, wrap my proxy class around original class, and delegate all method calls on proxy to the original, except setters which would also fire the PropertyChangeEvent.
Anyway I posted the full explanation and the code on my blog here:
http://clockwork-fig.blogspot.com/2010/11/javabean-property-change-listener-with.html

Categories

Resources