Aspect Dependence Graphs (ADG)
- Aspect Dependence Graphs (ADG) are intermediate representations that capture control-flow and data-flow dependencies within aspect code in AspectJ.
- They represent dependencies in advices, pointcut definitions, inter-type declarations, and methods using control, data, call, parameter, and membership edges.
- ADGs are woven with System Dependence Graphs (SDG) at join points to form a CASDG, enabling accurate dynamic slicing and comprehensive program analysis.
An Aspect Dependence Graph (ADG) is an intermediate, dependence-based program representation specifically devised to capture the control-flow and data-flow dependencies internal to aspect code in AspectJ programs. Analogous to the System Dependence Graph (SDG) used for base (non-aspect) Java code, the ADG models intra-aspect relations among advices, pointcut definitions, inter-type declarations (introductions), and methods declared within an aspect. ADGs enable the unification of aspect code and base code dependences within a single program representation, which, when integrated with SDGs through weaving edges at join-points, forms the Concurrent Aspect-oriented System Dependence Graph (CASDG). The CASDG underpins dynamic slicing algorithms for concurrent aspect-oriented programs (Ray et al., 2014).
1. Scope, Purpose, and Role of ADG
The ADG is constructed to represent all control and data dependences present within:
- Advice bodies (including before, after, around, after-returning, and after-throwing)
- Pointcut definitions (which select join-points but have no executable body)
- Inter-type declarations (introductions) that augment classes with new fields, methods, or interfaces
- Ordinary methods declared within aspects
The principal role of the ADG is to function as the core dependence abstraction for aspect code, mirroring the function of SDG for base code. Post-construction, each ADG is woven into the SDG at the locations (join-points) designated by its pointcuts, thereby enabling unified, program-wide dependence analysis and facilitating precise dynamic slicing across the entire aspect-oriented program (Ray et al., 2014).
2. Formal Structure and Mathematical Definition
An ADG is defined as a directed graph
where:
- is a finite set of vertices, each representing one of:
- Aspect-entry vertex (unique root)
- Advice-entry vertex (one per advice), with further nodes for statements and predicates within each advice
- Pointcut-entry vertex (one per pointcut)
- Introduction-entry vertex (for each inter-type declaration), with corresponding body nodes
- Method-entry vertex and body nodes for helper methods
- is the edge set, partitioned as:
- Control-dependence edges (): iff is control-dependent on (e.g., governed by an if-condition) within the same advice, introduction, or method.
- Data-dependence edges (): Classical def-use edges linking a definition vertex of to a subsequent use of , provided no intervening redefinition occurs.
- Call and parameter-passing edges (, ): Connect, for instance, advice entries to pointcut entries, as well as actual-in to formal-in and formal-out to actual-out parameter nodes.
- Aspect-membership edges (): Link the aspect-entry root to each advice, pointcut, introduction, and method entry in the aspect, ensuring hierarchical organization.
Formally, for an aspect ,
This structure provides a detailed graph model of aspect internals, supporting subsequent weaving into the CASDG (Ray et al., 2014).
3. Integration with System Dependence Graphs and CASDG Construction
The SDG models dependence relations in base (non-aspect) code. For a full aspect-oriented system, integration requires:
Construction of an SDG for the base code.
For each aspect , independent construction of its ADG.
Augmentation of the combined node and edge sets by adding weaving edges () denoting advice application.
At every join-point in the SDG that matches pointcut from aspect , the construction adds:
A weaving edge for each advice bound to , linking control to the advice.
Parameter edges between join-point actual parameters and the advice's formals, if applicable.
The resulting global graph is the CASDG:
This unified representation enables sound and complete dynamic slicing, accurately reflecting the semantics of woven aspect-oriented programs (Ray et al., 2014).
4. Construction Algorithm
The construction process is divided into four principal algorithmic phases:
SDG Construction:
- Build the SDG for the base code via conventional program analysis.
- Aspect-wise ADG Construction:
- For each aspect:
- Create an aspect-entry node.
- Build entry nodes and subgraphs for each pointcut, advice, introduction, and method.
- Use the method-dependence-graph constructor for advice, introduction, and method bodies.
- Attach membership edges from the aspect entry to all member entries.
- For each aspect:
- Weaving:
- For each matching join-point and pointcut:
- Insert weaving edges from the SDG to the advice-entries per aspect semantics.
- Add necessary parameter-passing arcs.
- For each matching join-point and pointcut:
- CASDG Formation:
- Merge all nodes and edges from SDG, ADGs, and weaving edges to produce the final CASDG suitable for dynamic analysis and slicing algorithms.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
procedure BUILD_CASDG(BaseCode, Aspects)
SDG ← BUILD_SDG(BaseCode)
for each Aspect A in Aspects do
N_AG(A) ← {eA}; E_AG(A) ← ∅
for each pointcut pc in A do
N_AG(A) ← N_AG(A) ∪ {e_pc}; E_AG(A) ← E_AG(A) ∪ { (eA→e_pc) }
for each advice adv in A do
(N_adv, E_adv) ← BUILD_MDG(adv.body)
let e_adv be the MDG's entry node
N_AG(A) ← N_AG(A) ∪ N_adv
E_AG(A) ← E_AG(A) ∪ E_adv ∪ { (eA→e_adv) }
for each inter-type declaration int in A do
(N_int, E_int) ← BUILD_MDG(int.body)
let e_int be the MDG's entry node
N_AG(A) ← N_AG(A) ∪ N_int
E_AG(A) ← E_AG(A) ∪ E_int ∪ { (eA→e_int) }
for each method m in A do
(N_m, E_m) ← BUILD_MDG(m.body)
e_m ← entry(MDG)
N_AG(A) ← N_AG(A) ∪ N_m
E_AG(A) ← E_AG(A) ∪ E_m ∪ { (eA→e_m) }
EW ← ∅
for each Aspect A in Aspects do
for each pointcut pc in A do
for each join-point j in SDG matching pc do
for each advice adv bound by pc do
e_adv ← entry-vertex of advice adv in N_AG(A)
EW ← EW ∪ { (j → e_adv) }
EW ← EW ∪ PARAM_ARCS(j, adv)
CASDG ← (SDG.nodes ∪ all N_AG(A), SDG.edges ∪ all E_AG(A) ∪ EW)
return CASDG
end BUILD_CASDG |
5. Theoretical Properties and Correctness
- Soundness: Every control-flow construct in advice, introduction, or method bodies yields precisely the control-dependence edges (). All def/use pairs result in corresponding data-dependence edges (). Membership edges ensure all members are hierarchically reachable. The correctness is underpinned by reusing known-sound SDG/MDG constructions for every aspect subcomponent.
- Completeness: No dependencies are omitted as the standard analysis algorithms are applied exhaustively to aspect internals. Aspects and base code remain separated until weaving, preventing cross-contamination of dependencies.
- Weaving Correctness: Weaving edges are inserted strictly where required by AspectJ join-point matching semantics. This guarantees that the resulting CASDG accurately models actual program execution semantics for slicing and other analyses.
No step-by-step proof appears, but the construction is formally justified based on the established soundness of component representations (Ray et al., 2014).
6. Illustrative Example
Consider the following simple AspectJ fragment:
1 2 3 4 5 6 7 8 9 10 11 |
public aspect ThreadAspect { public pointcut classic(): execution(void run()); before(): classic() { System.out.println("Starting aspect code for run"); } after(): classic() { System.out.println("Ending aspect code for run"); } } |
The corresponding ADG contains:
- A root aspect-entry node ()
- A pointcut-entry node () with no body (hence no further control or data dependence edges)
- Advice-entry nodes for the “before” and “after” advices (, ), each with local body nodes for their respective
printlncalls, including their internal control and data dependences
Aspect-membership edges connect to , , and . In the full CASDG, the SDG node representing each run() method execution is connected to these advice entries with weaving edges, ensuring precise modeling of the dynamic semantics: each execution of run() invokes the before and after advice in conjunction with the base code. This exemplifies the effective unification of aspect-oriented constructs within program slicing infrastructure (Ray et al., 2014).