I have commited an initial prototype of the array interception needed for POJO Cache. It
is available in svn in a separate branch:
| $ svn co
https://svn.jboss.org/repos/jbossas/projects/aop/branches/arrays/
jboss-aop-arrays
| $ cd jboss-aop-arrays/build
| $ build.sh
| $ cd ../aop
| $ build.sh -f build-tests-jdk50.xml
| $ build.sh -f build-tests-jdk50.xml loadtime-ga-test -Dtest=array
|
The test files are in jboss-aop-arrays\aop\src\test\org\jboss\test\aop\array and
configured in jboss-aop-arrays\aop\src\resources\test\array. The invocations and things
needed for the array interceptions are in
jboss-aop-arrays\aop\src\main\org\jboss\aop\array.
I will merge this code to trunk, once the POJO cache guys approve.
Brief details of how it works follow:
It was too hard (impossible?) to figure out who the owning object of the array is from the
bytecode, since as far as the VM is concerned, the target for the Xastore and Xaload jvm
instructions is the array itself. This is different from what happens when you read/write
a field directly, since the putfield and getfield instructions take the object containing
the fields as the target object.
So what we do now is replace ALL array access within classes caught by arrayreplacement
expressions
jboss-aop.xml
| <aop>
| <arrayreplacement class="POJO"/>
| <arrayreplacement expr="class(@ReplaceArrayAccess)"/>
| </aop>
|
so that the follwing
| arr[5] = 100;
| int i = arr[5]
|
becomes
| ArrayAdvisor.arrayWriteInt(arr, 5, 100);
| int i = ArrayAdvisor.arrayReadInt(arr, 5);
|
To determine if an array should be intercepted, if a field
1) is woven from a field() expression
and
2) is captured by an arrayreplacement expression
and
3) Is of type array or Object (since that can hold an array)
then we extend the existing hooks for the field write to register the array with an
"ArrayRegistry" if the new value is an array.
| class POJO{
| int[] array = new array[]{1,2,3};
| Object couldBeAnArray = 10;
| int[] notadvised = new array[]{1,2,3};
| int x;
| }
| <aop>
| <arrayreplacement class="POJO"/>
| <prepare pointcut="field(* POJO->array)"/>
| <prepare pointcut="field(* POJO->couldBeAnArray)"/>
| </aop>
|
| POJO pojo = new POJO();
|
In the above example only POJO.array gets registered with the ArrayRegistry. If we now
do:
| pojo.couldBeAnArray = new int[]{1,2,3};
|
pojo.couldBeAnArray gets registered in the ArrayRegistry.
If the ArrayAdvisor.arrayWriteXXX() and arrayReadXXX() methods does not find the passed in
array in the ArrayRegistry, it simply updates/reads the array. If the passed in array is
in the ArrayRegistry, and we have interceptors defined for arrays, we create an
ArrayElementReadInvocation or an ArrayElementWriteInvocation (actually a subclass
depending on the type of array) and invoke on that.
Since the "target" for an array access is the array itself, the array is the
TargetObject in the XXXArrayElementXXXInvocation classes. We only allow PER_VM scoped
interceptors to be used for arrays, and interceptors set up apply to ALL registered
arrays. They are defined using the arraybind keyword:
| <aop>
| <interceptor class="ArrayAccessInterceptor"/>
| <arrayreplacement class="POJO"/>
| <prepare pointcut="field(* POJO->array)"/>
| <prepare pointcut="field(* POJO->couldBeAnArray)"/>
| <arraybind>
| <interceptor-ref name="ArrayAccessInterceptor"/>
| </arraybind>
| </aop>
|
I will also introduce some arrayread and arraywrite keywords, so we can differentiate
whether an element is being read or written (arraybind intercepts both reads and writes).
The method ArrayRegistry.getArrayOwners(Object array), which is also accessible from
ArrayElementInvocation.getArrayOwners(), allows you to get hold of all references to the
array. it is returned as a list of org.jboss.aop.array.ArrayReference objects, each of
which contains information about one reference to the array. It gives you access to the
object containing the reference, the field this reference is stored in, and if the field
is an array containing the target array within one of its elements a list of the indexes
from the top of the field to get to the array.
View the original post :
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3996995#...
Reply to the post :
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&a...