Neglecting the fragility aspect of the pointcuts, AspectJ pointcuts are also unable to select all the possible join points. There are some computational patterns (also very simple) that cannot be captured by AspectJ [1]. The join points between two method calls or those bound to statements like if , while and expressions are the simplest examples of join points unselectable by the join point model of AspectJ.
The above piece of code shows a couple of such unselectable join points (marked by small red circles). The first is related to a boolean expression in a conditional statement; in this case the join point could be selected if the code were refactored and the expression is substituted by a call to a predicate encapsulating the original boolean expression. Unfortunately not always refactoring can be pursued or gives the desired results. For example, the second join point is already attached to a specific call to the fib() method. This is already a method call and apparently not distinguishable, at least in AspectJ, from any other call to such a method. Also annotations do not help since they are, at least in the Java annotation model, attached to the method definition and not to an expression/statement.
The coarse grain of the join point model and its dependency on the program syntax permit to capture only those join points available in the application call graph [2] without considering its position or context. So it is really hard to choose among join points associated to the same program element (e.g., among all the calls to a given method) and to select those join points not explicitly visible in the control flow graph (such as those attached to an expression or inside a loop). This often hinders to get a neat separation of concerns.
Tourwé, T., K. Gybels, and J. Brichau. On the Existence of the AOSD-Evolution Paradox. In Proceedings of SPLAT’03, Boston, MA, USA, Apr. 2003.
Kiczales, G., E. Hilsdale, J. Hugunin, M. Kersten, J. Palm, and B. Griswold. An Overview of AspectJ. In Proceedings of ECOOP’01, LNCS 2072, pages 327–353, Budapest, Hungary, June 2001. Springer.
What is @AspectJ? And How does it work?
We developed @AspectJ to overcome such a limitation.
Our approach to solve this problem goes in the direction of providing a mechanism to explicitly mark the desired join points as in the annotation-based pointcuts of AspectJ 5+ (but with a finer granularity) rather than towards considering the context where the desired join point should be or the application semantics as in Alpha , Blueprint and Pitλ .
The basic idea is to exploit the fine-grained annotation model provided by the @Java_ programming language to allow the programmer to mark join points associated to single statements, block of statements and expressions to extend the join point model of AspectJ with a couple of primitive pointcuts to match such annotations.
Similarly to the changes introduced by @Java with respect to standard Java, @AspectJ differs from standard AspectJ only for two new primitive pointcuts: @block («annotation type») and @expr («annotation type»). These new pointcuts match a block and an expression annotation respectively.
The join points described in the previous example can be described and matched as follows.
The two new annotations @OnCond and @OnCall are used to mark the interesting join points. Through the new primitive pointcuts the occurrence of these annotations can be matched and advice can be woven on the corresponding join points.
The new primitive pointcuts can be combined with all the traditional AspectJ pointcuts and used in any kind of semantic action (before, after and around).
A Complete Example: Software Parallelization.
The algorithm to calculate the Mandelbrot set is a perfect example of a purely iterative, parallelizable procedure that can be easily summarized by the following piece of code.
In this implementation of the algorithm to calculate the Mandelbrot set, we have annotated the block corresponding to the main for loop. The block annotation @InParallel takes one parameter grid . The parameter specifies the number of rows and columns of a square grid over which the computation might be spanned. If multi-threading is enabled, by way of an aspect, then the system spawns grid``×``grid threads. For instance, when grid=4 , the system spawns 16 threads.
The @AspectJ aspect above shows how the optional multi-threaded computation has been implemented. The pointcut doInParallel takes 4 arguments, all integers. The arguments are bound by the args expression that refers the @block . The first four local variables in the generate() method are in fact all integers. The first and second variables represent the initial coordinates of the drawing procedure. The third and fourth variables represent the size of the canvas on which the points will be drawn.
The pointcut has been bound to an around advice. The advice computes the size of the grid by first inspecting the annotated block using @Java's reflection API and computing the square of the grid value. Then it partitions the entire canvas in n = gridSize × gridSixe quadrants (nQuadrants ). If w, h are the width and height of the canvas, then each quadrant is (w/n)×(h/n). Finally, for each quadrant, a new thread is spawned. The coordinates of the quadrant are calculated by the getQuadrant() procedure (not shown in the Listing). The thread is encapsulated in a MyRunnable class, that takes a Rectangle representing the quadrant as its constructor, and just call AspectJ's proceed() with the correct coordinates and sizes. The interesting part is that by calling proceed() we are actually telling @AspectJ to continue with the execution of the annotated block but also substitute the old values of the local variables with those we are passing, that is, to compute only a quadrant of the canvas.
The result has been implemented in a simple Swing application as shown in the following movie. The movie should clearly show that the set is drawn by four distinct brushes (threads).
Your browser does not support the HTML5 video tag.
Getting started with @AspectJ
@AspectJ is currently distributed as a GNU/Linux RPM package file. It can be installed on every reasonably recent RPM-based distribution (See at the end of the page for a list of the tested platform).
To successfully install and use @AspectJ you should have the following software properly installed and configured on your system:
Installing @AspectJ involves the following steps:
Download the rpm binary distribution.
Ensure that the environment variable JAVA_HOME is defined and points to the correct location.
Install the package with the command: rpm -Uhv ataspectj-<version>.noarch.rpm
After the first installation you will be prompted to execute a configuration
script that will take care of completing the installation process.
At this point you can compile your @AspectJ-enhanced source code with the ataspectjc compiler and run the program through the standard Java virtual machine.
@AspectJ has been tested on the following operating systems:
Mandriva 2009, 2010
Fedora 13 and 14
CentOS 4.x and 5.x
@AspectJ Staff
The @AspectJ project is led by Walter Cazzola.
Marco Poggi has developed the first version of @AspectJ;
Edoardo Vacchi is maintaining the project.
References
Walter Cazzola and Edoardo Vacchi, Fine-Grained Annotations for Pointcuts with a Finer Granularity , in Proceedings of 28th Annual ACM Symposium on Applied Computing (SAC'13), Coimbra, Portugal, March 2013, ACM Press.
Marco Poggi. @AspectJ -- An Extension to the AspectJ Join Point Selection Mechanism to Support @Java Annotation Meta-Facility (In Italian). Master thesis, Università di Genova, Advisor Walter Cazzola. Genova, October 2009.