Bytecode manipulation to intercept setting the value of a field
-
11-10-2019 - |
Question
Using a library like ASM
or cglib
, is there a way to add bytecode instructions to a class to execute code whenever the value of a class field is set?
For example, let’s say I have this class:
public class Person
{
bool dirty;
public String name;
public Date birthDate;
public double salary;
}
Let’s say a section of code contains this line:
person.name = "Joe";
I want this instruction to be intercepted so the dirty
flag is set to true
. I know this is possible for setter methods -- person.setName (“Joe”)
-- as class methods can be modified by bytecode manipulation, but I want to do the same thing for a field.
Is this possible, and if so, how?
EDIT
I want to avoid modifying the code section that accesses the class, I'm looking for a way to keep the interception code as part of the Person
class. Are there a pseudo-methods for field access, similar to properties in Python classes?
Solution
There are two bytecodes for updating fields: putfield
and putstatic
(see http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc11.html). These will be found in the code for the using class, so there's no way to simply modify Person
.
OTHER TIPS
In short, you need to inject bytecode that does the following in the method of interest :
if (person.name.equals("Joe") {
dirty = true;
}
You cannot evaluate the field at instrumentation time - it has to be at runtime when the method is executing.
Regarding your question of how, try the following:
- Write the code in a test class and generate an ascii version of the bytecode to see what was generated. You can do this easily with
javap
.