• No results found

Evaluating data structures for runtime storage of aspect instances

N/A
N/A
Protected

Academic year: 2020

Share "Evaluating data structures for runtime storage of aspect instances"

Copied!
129
0
0

Loading.... (view fulltext now)

Full text

(1)

MASTER THESIS

EVALUATING

DATA STRUCTURES FOR

RUNTIME STORAGE OF

ASPECT INSTANCES

Andre Loker

FACULTY OF ELECTRICAL ENGINEERING, MATHEMATICS AND COMPUTER SCIENCE (EEMCS)

CHAIR OF SOFTWARE ENGINEERING

EXAMINATION COMITTEE

Dr.-Ing. Christoph Bockisch

(2)

Abstract

(3)

Contents

1 Introduction

1

1.1 Problem statement and goals . . . 2

1.2 Approach . . . 3

2 Background and Related Work

5

2.1 Instantiation policies . . . 5

2.1.1 First responsibility: Aspect-instance retrieval . . . 5

2.1.2 Second responsibility: Restriction . . . 8

2.2 Existing instantiation policies . . . 8

2.2.1 Association aspects . . . 8

2.2.2 Per-object instantiation . . . 13

2.2.3 Singleton aspects . . . 16

2.2.4 Other instantiation policies . . . 17

2.3 More related work . . . 19

3 Research objectives

20

3.1 Research questions . . . 22

3.2 Approach . . . 25

4 Unified model of instantiation policies

28

4.1 Definition of key tuples and query-key tuples . . . 30

4.2 The bind function . . . 31

4.3 Queries and thefind function . . . 31

4.4 Thestore function . . . 34

4.5 isExact . . . 35

4.6 Implicit instantiation . . . 35

4.7 Generic Storage Function . . . 35

4.8 Summary . . . 37

5 Criteria

39

5.1 Asymptotic time complexity . . . 39

5.2 Actually required time . . . 41

5.3 Memory usage . . . 45

6 Scenarios

46

6.1 Aspect-instance look-up . . . 46

7 Data structures

49

7.1 Arrays . . . 50

(4)

7.3 Tree-based data structures . . . 57

7.4 Tries . . . 60

7.5 Hash-based data structures . . . 63

7.6 Summary . . . 67

8 Benchmark

71

8.1 Statistically rigorous performance evaluation . . . 71

8.2 Implementation of the statistically rigorous methodology . . . 72

8.3 More implementation details . . . 73

8.4 Selected data structures . . . 74

8.4.1 ArrayStorage . . . 74

8.4.2 HashMapStorage . . . 76

8.4.3 CustomHashMapStorage . . . 77

8.4.4 TrieStorage . . . 79

8.4.5 SingletonStorage . . . 81

8.4.6 PerObjectStorage . . . 81

8.4.7 AssociationAspectStorage . . . 83

8.5 System specifications . . . 85

8.6 Results . . . 87

8.6.1 Exact queries . . . 89

8.6.2 Partial-Range Queries . . . 96

8.6.3 Full-Range Queries . . . 104

8.6.4 Small datasets versus large datasets . . . 109

8.6.5 Baseline implementation versus specialisation . . . 109

8.6.6 Recommendations for single-query scenarios . . . 110

8.6.7 Complex scenarios . . . 112

8.7 Threats to validity . . . 114

8.7.1 Threats to internal validity . . . 114

8.7.2 Threats to external validity . . . 115

9 Summary and Future Work

117

(5)

1 Introduction

The primary goal of aspect-oriented software development (AOSD) [1] is the en-capsulation of crosscutting concerns, that is, functionality which is required at potentially many different places in the code, into separated modules calledaspects. An aspect describes the behavioural effect1 of the crosscutting concern on the base program. In many cases the code that implements the functionality of the crosscut-ting concern needs to access state which is shared between multiple executions of that code. This shared state is encapsulated in aspect instances. Whenever the implementation of a crosscutting concern – theadvice– is executed, the shared state that belongs to that occurrence has to be retrieved by the execution environment. Retrieving the correct aspect instance for a specific advice invocation is the primary task ofinstantiation policies. As the retrieval of the aspect instances can occur many times during the execution of the program, we want it to be fast. Although the aspect-instance retrieval has been optimised for certain instantiation policies, we need to find a way to make it efficient for as many instantiation policies as possible.

In this thesis we focus on aspect-oriented execution-environments that have an aspect-definition language following the pointcut-advice approach [2, 3], such as AspectJ [4], JAsCo [5], CaesarJ [6] or Compose* [7].

An aspect needs to define which places of the program it affects. This definition is given in form of apointcut[1]. A pointcut is an expression that describes a set of

join points,which refer to points in time during the execution of a program. Join points are those points in time at which advice has to be executed. The pointcut typically refers to specific places in the base-code, for example, all places where a certain method is called or all places where a certain field is written to. Those places in the base-code referred to by a pointcut are called join-point shadows. These join-point shadows are static concepts which can be determined during the

weavingprocess. In contrast, join points aredynamic (runtime) concepts which can potentially occur at join-point shadows.

Aspects are comparable to classes in object-oriented languages in that they encapsu-late the specification of state and behaviour. Like classes, aspects can be instantiated at runtime, with each aspect instance holding its own copy of state variables (fields

orinstance variables in object-oriented languages). The definition of the actual beha-viour of the crosscutting concern is given by theadvicesof an aspect [2]. Advices are comparable to function bodies (ormethod bodies in object-oriented environments) in that they consist of executable code. Similar to methods, which are executed in

1

(6)

the context of an object, advice is executed in the context of an aspect instance. The state of the aspect instance can be used and modified from within the advice.

However, unlike functions or methods, advice is never invoked explicitly. Instead, the advice code is called implicitly whenever, during execution, a join point is reached that is matched by the pointcut associated with the advice. To execute the advice, the execution environment requires an aspect instance. Retrieving the aspect instance for a specific advice execution is the main responsibility of aninstantiation policy. Multiple instances of an aspect can exist at runtime. An instantiation policy defines the rules that determine which instance to use for a specific join point. In addition, an instantiation policy may instantiate aspects implicitly if no existing aspect instance can be reused for the given join point. If such implicit instantiation is not supported or not possible2, aspect instances need to be instantiatedexplicitly. As a secondary responsibility, instantiation policies can restrict the execution of advice: if the instantiation policy does not retrieve an aspect instance, the advice cannot be executed.

1.1 Problem statement and goals

Instantiation policies are themselves a cross-cutting concern in multiple respects. Firstly, they affect the application at runtime each time advice is executed. To preserve state between invocations, advice of an aspect is executed in the context of an instance of the respective aspect. It is the responsibility of the instantiation policy to determine the aspect instance each time the advice needs to be executed. That instance can be an existing instance or – if implicit instantiation is supported – a new instance. Because the instance look-up can happen potentially many times, it should be as fast as possible to reduce the overhead at runtime. The exact impact of aspect instance look-up is difficult to predict for the general case. However, Dufour et al. [8] have shown cases where setting up the arguments for advice execution – which the aspect-instance look-up is a part of – takes more than 26% of the total execution time. Optimizing the execution speed of aspect-instance look-up is therefore a desirable goal.

Secondly, instantiation policies are a cross-cutting concern in that they are part of the design-space of each aspect-oriented language which follows the pointcut-advice approach. The choice of available instantiation policies determines if and how easily certain usage scenarios are natively supported by an aspect-oriented runtime-environment. If an aspect-oriented runtime-environment does not support a

2

(7)

specific instantiation policy, users of this runtime-environment need to implement equivalent logic on their own to achieve the same behaviour. For example, if an aspect-oriented runtime-environment only supports the

singleton

instantiation policy, each advice invocation takes place in the context of the same aspect instance. To emulate for example the

pertarget

behaviour (which uses a different aspect instance for each distinct target object of a method call), users of this environment need to come up with their own means to share state between advice invocations for the same method-call target. This can potentially lead to duplicate implementations of the same concept, which is exactly what aspect-orientation tries to avoid in the first place. Because instantiation policies are cross-cutting concerns, they should be implemented as isolated, reusable modules instead.

Instantiation policies should also ideally be implemented within the aspect-oriented environment itself. Depending on the desired behaviour and the runtime-environment, some instantiation policies can be difficult to implement manually. For example, instantiation policies like

per-control-flow

[1] or

per-data-flow

[9] are – if at all – rather difficult to implement efficiently on the base-code level. The aspect-oriented runtime-environment on the other hand typically has access to additional information that is difficult to acquire from within the base code. The aspect weaver can analyse the code, potentially allowing for macro-level and micro-level optimisations because of certain usage patterns and other criteria.

The existing aspect-oriented environments differ in the available instantiation policies. We also expect new aspect-oriented environments to be be developed in the future. Being able to implement new instantiation policies quickly or migrating existing instantiation policies from one aspect-oriented execution-environment to another is therefore a desirable goal. To simplify the implementation of instantiation policies, having a generally applicable, but still efficient way to store and retrieve aspect-instances would be beneficial. For special cases, aspect-instance look-up can then still be further optimised where possible.

Thus, we have two main goals for this research. Firstly, aspect-instance look-up should befast, because it is expected to have considerable impact on the execution time. Secondly, implementing new instantiation policies for a given aspect-oriented execution-environment should be easy, because instantiation policies are cross-cutting concerns and are best implemented within the execution-environment.

1.2 Approach

(8)

instantiation-policies can vary considerably in their semantics, they all have to imple-ment aspect-instance look-up in one way or another. To make the impleimple-mentation of new instantiation policies easier, we will suggest a baseline approach to imple-ment aspect-instance storage and look-up. This baseline approach has to be generic enough to support as many instantiation policies as possible. At the same time, we want this approach to be efficient enough to be applicable in practice. Additionally, we will identify special cases in which aspect-instance look-up can be further op-timised if more specialised implementations are used, and we will describe those specialised implementations.

As an outcome of this thesis, we will provide an evaluation of representative data structures and algorithms with respect to their suitability for aspect-instance storage and look-up. We expect some data structures to be more efficient in terms of execution speed and memory usage than others in the context of aspect-instance storage, depending on the usage scenario. Therefore, we will provide a representative overview of expected usage scenarios and recommend specific data structures and implementation details for each scenario.

(9)

2 Background and Related Work

2.1 Instantiation policies

In aspect-oriented environments following the pointcut-advice approach, advice is typically executed in the context of an instance of the declaring aspect. This allows state to be shared between multiple invocations of the same piece of advice. An instantiation policy defines a set of rules that determine the aspect instance to be used for the execution of advice. An instantiation policy has two main responsibilities:

Aspect-instance retrieval

When advice is applicable at a join point, the instantiation policy needs to determine the aspect instance used as the context in which the advice is executed. During this process the instantiation policy needs to determine if an existing aspect instance is reused (and if so, which instance) or if a new aspect instance needs to be created. If aspect instances can be reused, the instantiation policy needs to keep track of those instances it has created for subsequent look-ups.

Restriction

An instantiation policy can define rules that restrict or enable the applic-ability of the advice when a join point covered by the pointcut of that advice has been reached. This responsibility allows an instantiation policy to affect the evaluation of a pointcut expression.

The semantics of an instantiation policy are determined by how the policy fills in these two responsibilities. We describe those responsibilities in more detail in the next subsections.

2.1.1 First responsibility: Aspect-instance retrieval

Because aspects often need to store state that is shared between individual invoca-tions of their advice, they must be instantiated at runtime [4]. An advice is invoked if, during the execution of the program, a join point is reached that is matched by the pointcut expression belonging to the pointcut-advice. The instantiation policy used by the aspect needs to retrieve the aspect instance (or in some cases multiple instances) that is used for a particular invocation of the advice.

(10)

combination of context values determines the aspect instance to use. For example, the

pertarget

instantiation policy in AspectJ [4] investigates the target object of a method call. For each distinct target object, a different aspect instance is used. For each subsequent advice invocation at join points with the same target object, the same aspect instance is reused, allowing for state to be shared between invocations. How the context values are used to determine (shared) aspect instances therefore largely determines the semantics of an instantiation policy.

Some instantiation policies allow multiple aspect instances to be retrieved for a single join point. This can occur if the pointcut expression and/or context values do not unambiguously dictate one specific instance to be used, but rather a range of instances. In that case the advice is executed once for each aspect instance retrieved by the instantiation policy.

At some point before the advice invocation, the actual instantiation of the aspect needs to take place. An advice is typically given as a piece of code written in the same programming language as the base code. As such, it follows the same paradigms as the base code. For example, in AspectJ the advice code is object-oriented like the base code. In fact, the AspectJ aspect compiler translates aspects to conventional Java classes [4]. The advice becomes a method of this class. Variables that store the state of the aspect between advice invocations become fields in the aspect class. To instantiate the aspect, an instance of that class is created.

We differentiate between implicit instantiationandexplicit instantiation [10]. In the case of implicit instantiation, aspect instances are created by the instantiation policy as needed. If, during aspect-instance retrieval, the instantiation policy eval-uates the context values and finds that there is no aspect instance for the current execution context yet, it creates a new instance of the aspect – typically by instanti-ating the respective class – and uses that instance as the context object for advice execution. The policy also needs to remember the instances it has created so that those instances can be reused for subsequent advice invocations.

Example 1. The

pertarget

instantiation policy in AspectJ uses implicit instantiation. When a join point is reached that matches the pointcut, the instantiation policy tries to find an aspect instance associated with the target of the current method call. When no such instance exists, it implicitly creates a new instance and remembers it for future reuse. The next time a join point with the same target object of a method call is reached, the instantiation policy reuses the aspect instance it has created

before.

(11)

from within the base code. The instances are then registered at the aspect-oriented execution-environment. When registering an aspect instance, the base code provides information about the cases in which to use the instance.

Example 2. Association aspects (Sakurai et al [10]), which use a different aspect

instance per pair of objects, use explicit instantiation. From the base code, a new instance of the aspect is created and then associated with a specific pair of objects. The special

associated(a,b)

pointcut expression is used to declare that a join point is only matched if an aspect instance was registered for the pair of objects

a

and

b

, where

a

and

b

are variables that are bound to actual context values by other pointcut expression such as

target(a)

. If an aspect instance was registered for that pair of objects before, that instance is used for the execution of the advice.

Implicit instantiation can only be performed if all information required for instan-tiating the aspect can be deduced at the moment of instantiation. For example, if the aspect depends on certain initialization arguments (like constructor arguments in Java), an instance can only be created if those dependencies can be resolved implicitly. Likewise, if the instantiation policy can potentially retrieve multiple aspect instances for a specific pointcut, it is typically impractical or even impossible to implicitly create the aspect instances because the set of required aspect instances cannot be determined unambiguously. Instantiation policies that support those cases need to rely on explicit instantiation.

Example 3. Association aspects support the use of wildcards in the

associated

expression. For example, the expression

associated(a,*)

would yield the aspect instances that have been registered to all pairs where the first element is

a

. In this situation, implicit instantiation would mean to implicitly create an aspect instance for each existing object that can appear as the second element of a pair of objects. As this is typically not a sensible approach, association aspects only support explicit

instantiation.

Different instantiation policies use different approaches to store and retrieve aspect instances. Often, those approaches are optimised for the specific policy.

Example 4. The

pertarget

instantiation policy implements aspect-instance storage

by adding a special field to each class that is a potential call target according to the advice’s pointcut3. When a new instance of the aspect is created, a reference to it is stored in the added field of the current call target. If some time later the object is again the target of a method call covered by the pointcut, the aspect-oriented execution-environment only needs to look at the added field of the current call target

to find the aspect instance.

3Because join point shadows are statically determinable in the source code, all classes of which

(12)

2.1.2 Second responsibility: Restriction

For advice to be applicable at a specific join point, all conditions in the pointcut expression of the pointcut-advice need to be satisfied. Explicit instantiation adds another condition, namely that an instance of the aspect must have been explicitly created for the current join point. If no suitable advice instance is found, the advice is not invoked. Therefore, an instantiation policy can provide additional restrictions to an aspect with respect to the applicability of advice. Unlike implicit instantiation, which does not restrict the applicability of an aspect, explicit instantiation can be used in cases where the aspect should only be applicable in selected circumstances.

Example 5. Association aspects can restrict advice execution. For example, a

pointcut expression such as

associated(a,b)

requires that an aspect instance for the pair of objects

(a,b)

has been registered explicitly. If no such pair has been registered, no aspect instance can be retrieved and therefore the advice is not

executed.

2.2 Existing instantiation policies

Available instantiation policies vary between aspect-oriented environments. The rest of this section describes several of those policies. We provide a description of the policies’ semantics and how the policies fulfil the two responsibilities introduced in Section 2.1.1, aspect-instance retrieval and restriction. In addition, we describe the instantiation policies from an abstract, conceptual point of view which allows us to generalise the concept of instantiation policies. This is necessary to recommend a generalised strategy for implementing new instantiation policies.

2.2.1 Association aspects

Overview

Sakurai et al. [10] present the concept of association aspects which associate aspect instances to combinations of

n

objects.

Association aspects extend the AspectJ language at several places. Firstly, the

perobjects

per-clause4 declares an aspect to be an association aspect. The

4

(13)

Listing 1: A simple association aspect [10]

1 aspect Equality perobjects(Bit, Bit) { 2 Bit left;

3 Bit right; 4

5 Equality(Bit l, Bit r) {

6 left = l; 7 right = r;

8 associate(l, r); // establish association

9 }

10

11 before(Bit l, Bit r) : call(* Bit.*(*)) && 12 this(l) &&

13 target(r) && 14 associated(l,r) {

15 System.out.println(String.format("Bit %s called method of Bit %s", left, right)); 16 }

17

18 after(Bit l) : call(void Bit.set()) && 19 target(l) &&

20 associated(l,*) {

21 right.set(); // propagate value change to "partner"

22 } 23 ...

24 }

perobjects

clause defines the number and the types of objects that take part in each association. Secondly, association aspects add a new pointcut primitive called

associated

. This primitive determines the (combination of) objects for which a spe-cific aspect instance needs to be retrieved. Finally, association aspects introduce a method called

associate

which establishes the association between an aspect instance and the set of objects for which that specific aspect instance has to be used.

We explain the extensions to AspectJ made by association aspects and their semantics in more detail by means of two examples.

Example 6. Establishing an association between multiple objects can be useful to

keep the state of those objects synchronised. For example, assume a class

Bit

[10] that represents a single bit. One might want to relate two bits in such a way that setting the value of one bit causes the value of the second bit to change accordingly.

(14)

Listing 2: The association aspect

NotificationLog

1 aspect NotificationLog perobjects(Observable, Observer) { 2

3 int counter; 4

5 NotificationLog(Observable observable, Observer observer){

6 associate(observable, observer);

7 }

8

9 before(Observable observable, Observer observer) : 10 call(void Observer.notify(*)) &&

11 this(observable) && 12 target(observer) &&

13 associated(observable, observer) { 14 counter++;

15 } 16 }

associate(l,r)

(line 8) establishes the association between the two

Bit

instances and assigns the current aspect instance to this association.

The

Equality

aspect defines two pointcut-advice bindings. The first (lines 11–16) is supposed to log any calls of the left

Bit

to an associated right

Bit

. A

this

primitive is used to bind the variable

l

to the currently executing object (line 12). Likewise, the

target

expression binds the current call target to the variable

r

(line 13). The

associated

primitive in line 14 requires that an association has been established between

l

and

r

. If this is the case, the advice will be executed in the context of the aspect instance assigned to this association.

The second pointcut-advice pair (lines 18–22) establishes the synchronisation between two bits: whenever the

set

method is called on the left

Bit

of a bit pair, the right bit should be notified about the changes. The pointcut binds the current call target (which must be a

Bit

) to variable

l

(line 19). Again, the

associated

primitive is used to check for an association of bits (line 20). However, in this case, a wildcard (an asterisk,

) is used as the second argument to the

associated

primitive, causing the pointcut to be applicable for all associations in which the left

Bit

is

l

. For each such association the advice is executed once in the context of the respective associated

aspect instance.

(15)

Listing 3: Modified object layout for association aspects

1 class Bit {

2 // fields added during weaving

3 Map<Bit,Equality> rightPartnersToAspectInstances; 4 Map<Bit,Equality> leftPartnersToAspectInstances; 5 ...

6 }

often the Observable notifies the Observer. Listing 2 shows an exemplary implement-ation of

NotificationLog

using association aspects. The

perobjects

keyword (line 1) declares that this aspect associates a pair of

Observable

and

Observer

. Calling the in-trinsic method

associate

(line 8) creates an association between the

Observable

and the

Observer

and assigns the current aspect instance to this association. The pointcut expression

call(void Observer.notify(*))

(line 10) defines that the advice will be executed when an

Observer

receives a call to the

notify

method. The object in whose context the call occurs is bound to

observable

(using

this(observable)

, line 11). The object receiving the method call is bound to

observer

(using

target(observer)

, line 12). And finally, the advice can only be executed if an aspect instance has been registered for this pair of

observable

and

observer

(

associated(observable,

observer)

, line 13).

Aspect-instance retrieval

When a pointcut is evaluated for an association aspect, the runtime tries to find an as-pect instance associated with the pair of objects referred to by the

associated(. . . )

expression. Those objects are typically context values such as the call target (

target(. . . )

) or the object in whose context the current method is executing (

this(. . . )

). To keep track of aspect instances, the AspectJ runtime has been augmented to modify classes that can take part in an association (that is, those types used in the

perobjects(. . . )

declaration of the aspect) during the weaving process. For a given association aspect each type that can take part in the association gets additional fields with information about existing associations.

Example 8. For the

Equality

example, the AspectJ runtime adds two fields to

the

Bit

class in a way similar to what is shown in Listing 3. The first field,

(16)

Listing 4: Instantiation of

Equality

[10]

1 Bit left = ... 2 Bit right = ... 3

4 // Instantiate Equality aspect and

5 // establish association between left and right bit.

6 new Equality(left, right);

runtime effectively calls

left.rightPartnersToAspectInstances.put(right, aspect)

and

right.leftPartnersToAspectInstances.put(left, aspect)

.

Storing the associations twice is necessary to support wildcards. The first field can be used to find associated aspect instances for pointcuts that use an expres-sion such as

associated(left, *)

, the second field is used for pointcuts with an expression such as

associated(*, right)

: the sought aspect instances are simply all values in the respective maps (

rightPartnersToAspectInstances

in the former case,

leftPartnersToAspectInstances

in the latter) and can be retrieved with a call to the

values()

method of the

Map

interface. If no wildcard is used, that is, both parts of the association are bound by an expression such as

associated(left, right)

, either the

rightPartnersToAspectInstances

of

left

or

theleftPartnersToAspectInstances

of

right

can be used: both

right.leftPartnersToAspectInstances.get(left)

and

left.rightPartnersToAspectInstances.get(right)

return the same aspect instance.

Association aspects always use explicit instantiation. An association needs to be es-tablished with a call to the method

associate

. The

associate

method is automatically added to the aspect class. The instance of the aspect on which

associate

is called is assigned to the established association. In the example given in Listing 1 the call is wrapped within the aspect constructor for convenience, thus the

Equality

aspect can be instantiated as shown in Listing 4.

Restriction

Because association aspects are instantiated explicitly, the applicability of advice can be restricted. An

associated

expression without wildcards will only match a join point if there is an association between the objects that are bound to that expression. There is either exactly one such association or none at all5. In the latter case no aspect instance can be determined. The advice will therefore not be executed. If wildcards are used, an

associated

expression can refer to zero or more associations. Again, if no association is matched by the expression, no advice is executed.

(17)

Conceptual view

Association aspects have the most general instantiation policy of all policies presented in this thesis. Therefore, we base our unified model (see Section 4) mainly on this policy. Specifically, two properties of association aspects are of importance to our unified model:

1. Aspect instances are associated to a tuple of objects. That is, for a specific combination of context values, a separate aspect instance is used.

2. When retrieving aspect instances for a given pointcut, wildcards are support. That is, at a given join point, multiple aspect instances can be applicable.

Association aspects are always explicitly instantiated. While this provides the restric-tion funcrestric-tion menrestric-tioned in Secrestric-tion 2.1.2, we also want to include implicit instantiarestric-tion in our model.

Although association aspects do not support implicit instantiation, this could be added as an extension of the original concept for cases where no wildcards are used. When no wildcards are used inside the

associated

expression, at most one aspect instance can be retrieved6. If the association referred to by an

associated

expression has not been established before, the execution environment creates a new instance of the expected aspect, calls

associate

on it with the argument provided to the

associated

expression and uses the new aspect instance as the instance for the advice invocation.

2.2.2 Per-object instantiation

Overview

Per-object instantiation is supported by most aspect-oriented frameworks such

as AspectJ [4], AspectWerkz [13, 14] or JAsCo [5]. Different flavours of per-object instantiation policies exist, but they have in common that they refer to a specific value in the context of the join point (for example, the object in whose context the current method is executing) and that they create a different aspect instance for each distinct instance of that context value. In this section, we concentrate on the flavours provided by AspectJ.

6

(18)

Listing 5: Examples for theperthisandpertargetinstantiation policies.

1 aspect PerThisExample perthis(bitSetter()){ 2 pointcut bitSetter(): call(void Bit.set()); 3 before(): bitSetter() {

4 // advice body...

5 }

6 } 7

8 aspect PerTargetExample pertarget(bitSetter()){ 9 pointcut bitSetter(): call(void Bit.set()); 10 before(): bitSetter() {

11 // advice body... 12 }

13 }

AspectJ supports two different per-object policies, perthis and pertarget . The

perthis policy, indicated by a

perthis

per-clause, creates a new instance of the

aspect for each distinct object in whose context the current method is executing. The

pertarget, similarly denoted by a

pertarget

per-clause, is used with pointcuts that refer to method calls. It creates a new aspect instance for each distinct target object of the method call, that is, the object that receives the method call.

Example 9. The first aspect in Listing 5 (lines 1–6) shows an exemplary use of the

perthispolicy. The aspect is declared to use the

perthis

policy (line 1). The

perthis

per-clause expects a pointcut expression as an argument. In this case, for each distinct object calling

Bit.set()

(line 2), a new aspect instance will be created. The second aspect in Listing 5 (lines 8–13) shows the use of thepertargetpolicy. In this example, a new instance of the

PerTargetExample

aspect is created for each distinct target of the call to

Bit.set()

. In other words, the aspect is instantiated once for each distinct

Bit

that has its

set()

method called.

Aspect-instance retrieval

(19)

expression

call(void Bit.set())

will cause the

Bit

class to receive the field. When the aspect instance needs to be accessed, it is searched for in the added field. If the field has a value of

null

, no instance of the aspect has been created for the respective object yet.

Listing 6: Implementation ofpertarget: an additional field is added to target classes.

1 class Bit { 2 ...

3 private PerTargetExample perTargetExampleInstance; 4 ...

5 }

Example 10. A simplified example for the implementation of

PerTargetExample

is

shown in Listing 6. When weaving the aspect into the base code, the AspectJ weaver adds a field to the target class

Bit

. To retrieve the aspect instance for advice execution, the AspectJ runtime looks it up in the

perTargetExampleInstance

of the current call target (which must be of type

Bit

).

Like all instantiation policies that AspectJ provides, perthis and pertarget only support implicit instantiation. At join points that are covered by the pointcut passed to the

perthis

or

pertarget

per-clause (e.g., in the case of

PerTargetExample

, calls to

Bit.set()

), the execution environment checks whether the generated field has an aspect instance assigned to it. If it does not, that is, its value is

null

, a new instance is created implicitly by the execution environment; otherwise the existing instance is used.

Although AspectJ does not support explicit instantiation, this restriction is not inher-ent for per-object instantiation. Other aspect-oriinher-entation execution environminher-ents support explicit per-object instantiation policies that allow aspects to be (deployed to and) instantiated for selected objects only [16].

Restriction

Per-object instantiation in AspectJ does not have a restriction function, because aspect instances are always created implicitly on demand. For implementations that do support explicit instantiation, the restriction function applies as described in Section 2.1.2.

Conceptual view

(20)

instance. Aside from the implicit instantiation, the per-object policies of AspectJ (perthisandpertarget) can be completely expressed by association aspects as well. In both cases, the tuple used in the association is unary, that is, the tuple consists of only one element. The only difference is the context value used for this element. An example is shown in Listing 7. In the pointcuts, the policy is enforced by passing the current

this

(for

perthis

, line 2) or the current call target (for

pertarget

, line 6) to the

associated

expression. Both

perthis

and

pertarget

, however, support implicit instantiation, which is by default not supported by association aspects.

Listing 7:perthisandpertargetexpressed as association aspects

1 aspect SomeAspect perobjects(Bit) {

2 before(Bit b) : this(b) && associated(b) { 3 // ...

4 }

5

6 before(Bit b) : target(b) && associated(b) { 7 // ...

8 }

9 }

2.2.3 Singleton aspects

Overview

Some aspects share their state between all advice invocations. These aspects are often called singleton aspects, because at most a single instance of the aspect is created in whose context advice is executed.

The singleton instantiation policy is calledissingletonin AspectJ [4] andperJVMin AspectWerkz [13, 14], the latter stating more clearly that the aspect is instantiated only once per virtual machine instance. By default, when no other instantiation policy is used, aspects are singleton aspects in both AspectJ and AspectWerkz.

Aspect-instance retrieval

(21)

Instances of singleton aspects are implicitly created by the AspectJ execution en-vironment the first time the advice needs to be invoked. To determine whether an instance exists, the execution environment only needs to check whether the created static field in the aspect class has an instance assigned to it. If not, a new instance is created and its reference is stored in that field for future reference. Otherwise, the object referenced by the field is reused.

Restriction

Like per-object instantiation (Section 2.2.2), singleton instantiation in AspectJ does not impose a restrictive function.

Conceptual view

Singleton aspects can be considered a trivial case of the instantiation policy used with association aspects. The arity of the associated tuples is zero in this case. Therefore, at most one association exists in this case: the association between the empty tuple and the singleton instance of the aspect. Listing 8 shows an example of how this can be represented conceptually. Again, the

perobjects

per-clause is used to make the aspect use the association-aspect instantiation-policy (line 1). However, the provided type tuple is empty (a 0-tuple). The pointcut in lines 2–3 uses the

associated

expression to check for an existing association of the 0-tuple. Because association aspects only support explicit instantiation, the pointcut will not be matched if no such association has been established before (with a call to

associate

). However, singleton aspects use implicit instantiation. To completely represent singleton aspects by association aspects, we assume that the association is implicitly established.

Listing 8: Conceptual example of singleton aspects as association aspects

1 aspect SomeAspect perobjects() { // associations of 0-tuples 2 before() : associated()

3 && call(void Bit.set()) { 4 // ....

5 }

6 }

2.2.4 Other instantiation policies

(22)

AspectJ supports thepercflow(andpercflowbelow) instantiation policy which asso-ciates a new aspect instance with each occurrence of a specific control flow whose start is defined by a given pointcut. Unlike the objects that are used as the key in the association to aspect instances, control flows are not represented as explicit objects in the Java runtime, which means that AspectJ cannot store aspect instances with

percflowinstantiation by modifying the layout of certain objects. Instead AspectJ uses a thread-local stack that keeps track of control flows that have been entered and exited. This strategy can be expressed by an association-aspects policy that establishes associations of aspects and unary tuples consisting of a “cflow”. However, because a control flow is not a first class entity in Java, it is a more abstract concept than a conventional Java object. Even though percflowconceptually fits into our generalised model, we will therefore not further consider this policy in our research.

Masuhara and Kawauchi [9] have suggested data-flow pointcut-expressions. A data flow is defined by the usage of the same object at two different join points, one that matches the current join point and one that has matched a join point in the past. Ensuring that data is encrypted while it flows through the system is an example use-case. Although the authors do not introduce a distinct instantiation policy for per-data-flow aspects, one can imagine aspects being instantiated once for each data flow identified in a data flow pointcut. Aper-dataflowinstantiation policy can be considered an extension of thepercflowpolicy. Again, we will not include it in our research, even though it conceptually fits into our model.

Older versions of AspectWerkz [13, 14] provided support for aper-thread instan-tiation policy. This policy can be considered a special case of per control-flow instantiation with the control flow starting at the first stack frame of a specific thread. The support for per-thread instantiation was dropped in version 2 of AspectWerkz. JAsCo [5] also supports per-thread instantiation.

Other instantiation policies supported by JAsCo includeper-class(one instance for each distinct type of the target object of a call) andper-all(one instance for each distinct join point shadow). Per-classinstantiation can be simulated by association aspects as it is similar to thepertargetpolicy, if instead of the call target itself its type is used to determine whether a new or existing aspect instance is used.

(23)

2.3 More related work

In preparation to this thesis, we already established a first abstract model of instanti-ation policies [17]. Although the initial model already captures the essential ideas of our current unified model (see Section 4), it does not clearly distinguish between those parts of instantiation policies that define their semantics and those parts that are independent of any semantics and may therefore be more easily generalised. We also evaluated the asymptotic complexity of algorithms that can be used to represent aspect-instance storage.

In collaboration with Steven te Brinke and Christoph Bockisch, an article has been published for the 2012 FREECO Conference [18]. The unified model presented in that article defines instantiation policies in terms of animplicitflag and the functions

bind,find and store. The unified model described in this thesis is based on and extends the model presented in that article.

Martin Zandberg evaluated optimisation of aspect-instantiation strategies using JIT compilation [19]. Based on the unified model, he identified properties of instantiation-policies:

• implicit versus explicit instantiation

• context-sensitive policies versus context-insensitive policies – that is: does the aspect-instance in the context of which advice is executed depend on context variables (such as the object that is calling the currently executed method)?

• exact queries versus range queries – that is: are there potentially multiple aspect instances applicable at the current join point?

• fixed associations versus non-fixed associations – that is: can the aspect instance for a specific join point be exchanged once it has been deployed?

For each combination of those properties7, Martin Zandberg suggests an optimized implementation to access the underlying data storage for the aspect instances, when implemented in the ALIA4J framework using JIT compilation. Zandberg’s thesis focuses on optimising the machine code generated for the look-up procedure, based on properties of the different instantiation policies. The underlying data structures are mostly left as an implementation detail. In contrast to that, this thesis focuses on the effect of the choice of data structures, independent of the compilation model or the aspect-oriented execution-environment. We expect the results of thesis to be combinable with the findings of Martin Zandberg.

7

(24)

3 Research objectives

Aspect orientation deals with crosscutting concerns in software systems [20]. The join-point shadows that result from the deployment of an aspect can potentially exist in parts of the program that are executed many times. Whenever the program execution reaches a join-point shadow, the aspect-oriented execution-environment needs to decide whether that shadow is an actual join point by evaluating the related pointcut of the aspect [4]. As described in Section 2.1, one part of this evaluation is the retrieval of the aspect instances for which the advice will be executed. This part of the pointcut-evaluation process, which is also depicted in Figure 1 on page 21, works as follows:

• First, the instantiation policy tries to find one or more aspect instances using a specific combination of values from the execution context (1). The combination

ofcontext valuesdetermines which aspect instances of all known instances

to retrieve. Which context values are used depends on the policy’s semantics (Section 2.1.1). For example, thepertarget instantiation policy defines that there is (at most) one distinct instance of the aspect for each different target object of the current method call. The instantiation policy will therefore re-trieve the aspect-instance that is associated with that target object, if such an associated aspect instance exists. Specifically, the AspectJ implementation of thepertargetpolicy looks for an aspect instance in a field that has been added to the class of the target object during the weaving process.

• The initial look-up can be either successful or unsuccessful, that is, aspect instances matching the selection of context values may or may not have been found (2). If aspect instances have been found, the pointcut evaluation can continue (3). A pointcut can consist of several sub-expressions. A join-point shadow is only considered a join point (and therefore advice is executed) if all sub-expressions of the pointcut can be evaluated successfully and if aspect instances have been retrieved. Even if an aspect instance has been retrieved, other sub-expressions may fail to evaluate successfully. For example, the condition required by an if pointcut-primitive [11] may not be met at the moment of pointcut evaluation.

(25)

U1) Look7up7aspect

instanceUs)7for context7values.

U2)

Instance7found? No No

Yes

Yes

U4) Implicit7 instantiation

possible?

U7)

Stop7pointcut7evaluation7 immediately. Do7not7execute7advice.

U5) Instantiate7aspect

U6) Store7aspect

instance

U3) Continue7pointcut

evaluation.7Use found7instances7for

[image:25.595.91.512.152.601.2]

advice7execution.

(26)

• If implicit instantiation is possible, a new instance of the aspect is created (5) and stored for later retrieval (6). The pointcut evaluation may then continue (3). If all other sub-expressions of the pointcut are evaluated positively, the advice can be executed using the newly created aspect instance.

Aspect-instance retrieval needs to be performed on each evaluation of the join point shadow. Because this evaluation can occur many times during the execution of the program, we want it to be fast. If the evaluation of join points in general and the aspect-instance retrieval in particular takes too long compared to the actual advice execution, aspect-orientation may turn out to be inapplicable for performance critical applications. Therefore it is important to use data structures and algorithms that make aspect-instance retrieval fast.

3.1 Research questions

In this thesis we answer the following questions:

1. Which operations are required to implement instantiation policies in general?

We provide a unified model of instantiation policies that shows that an instantiation policy can be viewed as a function that maps tuples of context values to aspect instances. The unified model identifies the core properties and functions that define the semantics of an instantiation policy, namely bind and the implicit flag. In addition, an instantiation policy requires operations for aspect-instance retrieval

andstorage.

2. Which operations can be optimised without affecting the semantics of instantiation

policies?

(27)

that is, ignoring certain elements of the context-value tuple) as well asinsertion. Of those, we are primarily interested in the query operations, as we expect querying to occur much more often than insertion and thus to have a greater impact on the program execution. We will therefore evaluate insertion as part of our theoretical analysis, but not as part of practical evaluation. There are additional operations that we intentionally left out, such as copying data from one data structure to another (basically a combination of a full-range query and insertion) and removal of elements. Even though some aspect-oriented execution-environments allow the removal of aspect instances or the full undeployment of aspects at runtime, we do not consider it to be a typical use case. We do not expect this omission to considerably affect the validity of our results (see Section 8.7).

3. What is the asymptotic computational complexity of the required operations when

im-plemented for different data structures?

Operations can be classified in terms of their asymptotic computational complex-ity [21]. It can be used to quantify the time and space requirements of an algorithm when the size of the data that it works on approaches infinity. Operations with the same asymptotic complexity show a similar growth in time requirements with increasing input sizes. Specifically we are interested in having an upper limit of the growth of the time and space requirements of different algorithms. This upper limit is usually described using the Big-O notation [22]. Knowing their complexity classes allows us to classify different algorithms.

4. What is the data complexity of the respective data structures in those scenarios?

The execution speed is not the only criterion to evaluate the suitability of a certain data structure for storing aspect instances. Memory also needs to be considered. Depending on the requirements of the application and the environment it runs in (for example, mobile device), the amount of memory that can be used to store aspect instances is limited. Consequentially, the amount of memory used must also be considered.

5. How do query operations perform in scenarios where the number of aspect instances is

comparatively small?

(28)

used by instantiation policies may be comparatively small. In the case of aspect-instance retrieval, the number of context variables (that is, the tuple size in our unified model) and the number of existing aspect instances determine the size of the input dataset for the operations needed by instantiation policies. Practical use cases are imaginable in which actually only a small number of aspect instances (for example, only a few dozen or hundred) exist simultaneously. Therefore, we expect the size of the input dataset to be far from “infinite”8. As a result, the asymptotic complexity may not give sufficient information about how the operations behave in practice. We expect different operations with the same asymptotic complexity to potentially perform notably different when the input size is comparatively small: constant overhead or other factors which are ignored by the Big-O notation can become important in those cases. Also, worst case scenarios may be more or less likely in practice, resulting in a different performance.

6. How efficient are operations on data structures that are generally applicable in all

scen-arios in comparison to operations on optimized data structures that can only be used in

specific circumstances?

Most instantiation policies in current aspect-oriented execution environments are rather simple. For example,singletonaspects [4, 13, 14] can only be instantiated once. Theperthisandpertargetinstantiation policies in AspectJ [4] relate at most one object from the set of context variables to an aspect instance. Those simple cases provide opportunities for optimisation, for example by changing the object layout during the weaving process [15]. We want to find out how data structures that can be used for any instantiation policy perform in comparison to those optimized structures.

7. Which data structure is recommended in which practical scenario?

Our solution must be generally applicable. Although special cases can possibly be optimised, we want to provide a solution that is fast in the general case. “Fast” in this case is only relative. The time and space used by the operations and algorithms can be compared with each other. However, an absolute definition of “fast” is difficult, as it highly depends on the requirements of the respective use case. We can therefore only evaluate the efficiency of the operations and data structures in abstract, relative terms. Nevertheless we want to provide a recommendation that is applicable for current as well as future, more complex instantiation policies.

8Additionally, there are practical limits to the number of objects that can be instantiated at a time,

(29)
[image:29.595.200.395.90.418.2]

Figure 2: Products of the thesis. Arrows represent order of production.

Answering the research questions will help the developers of aspect-oriented execution-environments to improve the speed of their implementations. As a result the applicability of aspect-orientation in performance-critical parts of applications can be improved. Also, we expect the development of new, more complex instantiation policies to be simplified because our solution is generally applicable.

3.2 Approach

(30)

As a first step, we establish aunified model of instantiation policies(see Section 4). We create the model as a refinement of our previous models ([17, 18]). It is based on the analysis of a selection of existing9 instantiation policies. The model allows us to represent all instantiation policies we consider using one unified concept, which primarily is the mapping of an

n

-ary tuple to an aspect instance. The model influences the design of the benchmark and the pre-selection of data-structures to evaluate (see below). This step answers our first two research questions (answers are found in Section 4.8).

The operations defined in the unified model also help us establishing a set of

scen-arios that we use to evaluate the data structures (see Section 6). There is only

limited information about the scenarios that occur in real-life applications. However, we chose a number of (what we think are) realistic scenarios that cover most of the possibilities of today’s aspect-oriented execution-environments that use a pointcut-advice approach. Primarily we focus on aspect instance look-up using different key-tuple lengths and differently sizes of input data. Theevaluation criteriathat we use to evaluate the scenarios (asymptotic time complexity, actual execution time and memory usage) are already defined by the research questions 3 to 5. We give a more in-depth description of these criteria in Section 5.

With the scenarios available we assemble a selection ofdata structuresto evaluate (see Section 7). Given the virtually infinite number of existing data structures and their derivatives, we are required to systematically select a short-list of data structures that we want to evaluate. The unified model suggests that instantiation policies are basically a function from tuples to aspect instances, or more generally from keys to values. This makes associative data structures[23, ch. 4] a good choice, that is, data structures that associate avalueto a specifickey. Typical examples for those data structures include hash maps and sorted trees ([24, 25]). Theoretically, any data structure can be used to store those associations, but some classes of data structures are better suited for this task because they are specifically designed for efficient key look-ups. In addition to associative containers we evalute simple data structures such as arrays and linked lists. The theoretical evaluation of the data structures answers question 3 and 4 (for the answers, see Section 7.6).

Next, we present the result of abenchmarkthat was used to execute the scenarios established earlier using the chosen data structures (see Section 8). The benchmark has been carefully developed to make the results reproducible and meaningful. However, the results are not meant to exactly quantify the execution speed of the operations or the amount of memory used, as those depend on many different factors. Instead, we were looking for qualitative statements about the relative behaviour of the different data structures as those are expected to be consistent in all real-life

(31)

Research question Answered in

1. Which operations are required to implement instantiation policies in general?

Section 4.8

2. Which operations can be optimised without affecting the semantics of instantiation policies?

Section 4.8

3. What is the asymptotic computational complexity of the required operations when implemented for different data structures?

Section 7.6

4. What is the data complexity of the respective data structures in those scenarios?

Section 7.6

5. How do query operations perform in scenarios where the number of aspect instances is comparatively small?

Section 8.6.4

6. How efficient are operations on data structures that are generally applicable in all scenarios in comparison to operations on optimized data structures that can only be used in specific circumstances?

Section 8.6.5

[image:31.595.95.523.101.311.2]

7. Which data structure is recommended in which practical scenario? Section 8.6.6

Table 1: Research questions and references to section in which they are answered.

cases. The benchmark together with the scenarios and evaluation criteria helps us to answer the research questions 5 (Section 8.6.4) and 6 (Section 8.6.5).

Finally, evaluate the results of the benchmark by comparing the influence of different variables (such as the number of aspect instances or the length of the query-key tuple) on the execution time of the queries performed by different algorithms. This allows us to qualitatively compare the performance of data structures and algorithms in different scenarios. The evaluation leads to a recommendation for the most suitable data structure to be used in specific scenarios according to our criteria (see Section 8.6.6). This final step answers the seventh, final research question.

(32)

4 Unified model of instantiation policies

In Section 2.2 we presented a number of instantiation policies and gave a conceptual overview of how they work. Comparing existing instantiation policies, we found certain commonalities between them: instantiation policies have in common that they establish anassociation between a specific selection of context values and an aspect instance. That is, a specific selection of context values identifies a specific aspect instance. We call this selection of context values thekey-tuple(an ordered sequence of

n

elements). The instantiation policy defines the rules how the key tuple is constructed from context values.

The semantics of an instantiation policy is defined by two properties. Firstly, whether the instantiation policy uses implicit or explicit instantiation. And secondly, how the key tuples that identify aspect instances are created during the pointcut evaluation. We call the property that defines whether an instantiation policy uses implicit instanti-ation or not, theimplicit flag– a Boolean variable that has the value

true

for policies that use implicit instantiation and

false

for those that use explicit instantiation. We call the function that creates the key tuple at the moment of pointcut evaluation,

thebind function. When the pointcut is evaluated, the bind function generates a

key tuple consisting of values available from the execution context provided by the oriented execution-runtime. This key is used to search for candidate aspect-instances in whose context the advice is executed. The actual look-up operation is independent of a policy’s semantics. Although the implementation of the look-up operation and the underlying data storage can often be (and in practice often is) optimised for specific instantiation policies, changing it does not alter the behaviour of the instantiation policy. This separation of semantically relevant and irrelevant parts allows us to modularise the implementation of instantiation policies.

Each of the two properties (implicitflag andbindfunction) affects both respons-ibilities of an instantiation policy (Figure 3 on page 29). Aspect-instance retrieval depends on the bind function, as this function creates the key tuples: only those aspect instances are retrieved that are identified by the generated key tuple. Also, the restriction responsibility is affected by the bind function, as restriction only takes place if the bind function generates a key tuple which does not identify any existing aspect instance. The implicit flag affects both the aspect-instance retrieval and the restriction responsibility, because it determines how to handle cases in which no existing aspect-instances are retrievable. If this flag is set to

true

a new instance will be created as part of the aspect-instance retrieval. If the flag is set to

false

, restriction comes into effect, causing the advice not to be executed at all.

(33)
[image:33.595.133.471.97.324.2]

Figure 3: The relation between the semantic properties and responsibilities of instan-tiation policies.

context of the execution, such as local and global variables or the pointcut that is being evaluated. The implementation of

Context

is provided by the actual aspect-oriented execution-environment. The second parameter, an

InstantiationPolicy

, provides an abstraction of the four characteristics that vary between different in-stantiation policies: bind,implicit,findand store. Bindandimplicitdefine the semantics of the policy. Findandstoreare respectively responsible for looking up and “remembering” associations between key tuples and aspect instances. We do not make assumptions about the implementation offindandstorein this unified model. However, we provide a generic abstraction (Section 4.7) and suggest different ways to implement it (Section 8.4).

To retrieve aspect instances,

bind

creates – according to the semantics of the instan-tiation policy – aquery-key tupleconsisting of values from the execution context and possiblywildcards.

Find

then uses this query key to look up associated aspect instances. If no matching instances can be found and the policy supports implicit instantiation, a new aspect instance is created. In such a case, the runtime environ-ment calls

store

to remember the association between the query key and the aspect instance for later look-ups.

(34)

Algorithm 1Generic algorithm to retrieve all applicable instances of an aspect. 1: functionRetrieveAspectInstances(

c

:

Context

,

ip

:

InstantiationP olicy

) 2:

keyT uple

ip.bind

(

c

)

3:

candidates

ip.f ind

(

keyT uple

)

4: if

candidates

=

and

isExact

(

keyT uple

)

and

ip.implicit

then

5:

newInstance

newA

6:

ip.store

(

keyT uple, newInstance

)

7:

candidates

← {

newInstance

}

8: end if

9: return

candidates

10: end function

4.1 Definition of key tuples and query-key tuples

Let each

T

i for

i >

0

represent an arbitrary type in the base code or the special

type

Any

(which represents any type). Furthermore, let

I

Ti denote the set of all

instances of type

T

i or any specialisation derived from it, that is,

I

Ti

=

{

o

|

o is a T

i

}

,

where

x is a T

if and only if

x

is of type

T

or a subtype (specialisation) of

T

. We define the (type of)key tuples

K

Aof one specific aspect

A

to be ordered sequences of

n

elements of the type:

K

A

:

I

T1

×

I

T2

×

...

×

I

Tn−1

×

I

Tn.

Example 11. In our

NotificationLog

example (Listing 2), each unique pair of an

Observable

and an

Observer

is associated with a distinct instance of the aspect. The set of key tuples for this aspect is defined as

K

N otif icationLog

:

I

Observable

×

I

Observer.

An exemplary key tuple

k

of this aspect is

k

= (

x, y

)

, where

x

I

Observable and

y

I

Observer, or put simply: a pair of an observable and an observer.

Example 12. The

pertarget

instantiation policy creates an association between a

single object (the target of a method call) and an aspect instance. As the instantiation policy does not constrain the actual type of the target object, the key tuple in this

case can be defined as

K

A

:

I

Any.

In addition, let

be a specialwildcardvalue. We definequery-key tuples

K

A∗ to be the set of ordered sequences of length

n

where each element is either an instance of type

T

ias defined above or the wildcard value, that is

K

A∗

:

I

T1

∪ {∗} ×

I

T2

∪ {∗} ×

...

×

I

Tn−1

∪ {∗} ×

I

Tn

∪ {∗}

. Note that

K

A

K

A, so each key tuple is a valid query-key

tuple. We define the boolean function

isExact

(

k

:

K

A

)

to return

true

if and only if

p

k

(

p

6

=

)

, that is, if

k

does not contain a wildcard. If a query-key tuple isexact, it is also a valid key tuple. That is,

isExact

(

k

:

K

A

)

k

K

A.

(35)

4.2 The bind function

During aspect-instance retrieval, the instantiation policy creates a query-key tuple to identify the aspect instances (if any) that are applicable at the current join point. The query-key tuple is constructed by the function

bind

:

Context

K

A∗. Given the current execution context, the function returns a query-key tuple, that is, a sequence of context values or wildcards. This key is used in a later step to retrieve matching aspect instances. Thebindfunction is specific for an instantiation policy and possibly also for a specific pointcut.

Example 13. As shown in Algorithm 2, thepertargetpolicy defines

bind

to always

return a query-key tuple containing the target of the current method invocation. This behaviour is equal for all usages ofpertarget. It does not depend on the pointcut expression that is being evaluated for aspect-instance retrieval.

Algorithm 2The bind function of thepertarget policy. 1: functionBind(

c

:

Context

)

2:

target

c.getCallT arget

()

3:

tuple

(

target

)

4: return

tuple

5: end function

Example: unlike the bind function of

pertarget

, the bind function used in the case of an association-aspect depends on the pointcut expression and the size of the key tuple. Association aspects use the explicit

associated(...)

expression to determine the content of the query-key tuple. The variables referred to by

associated(...)

need to have been bound to specific context values. In the case of

NotificationLog

(Listing 2), the two variables used in the

associated(...)

expression are bound to the current caller (

this

) and the target of the invocation of

notify

(the

target

or callee) respectively. The

bind

function for this aspect retrieves those objects from the context and creates a query key tuple from them. Algorithm 3 shows a possible implementation of

bind

for the

NotificationLog

example. The size of the generated tuple and the elements are specific for this example. If instead

associated(observable, *)

was used, the second element of the key tuple would be

the wildcard value

.

4.3 Queries and the

find

function

The function

f ind

: (

k

:

K

A

)

→ P

(

I

A

)

takes a query-key tuple and returns a set of

Figure

Figure 1: Aspect-instance retrieval as part of the pointcut evaluation.
Figure 2: Products of the thesis. Arrows represent order of production.
Table 1: Research questions and references to section in which they are answered.
Figure 3: The relation between the semantic properties and responsibilities of instan-tiation policies.
+7

References

Related documents

San Diego Quantum Capital Management San Francisco Rand &amp; Associates San Francisco Sand Hill Global Advisors Palo Alto Saratoga Research &amp; Investment

Based on household survey using a structured questionnaire in four study villages (N=684) in Vientiane Municipality during 2007–08 we analyzed the role and performance of the

*The reason that Elimination of Group Conversion (0.5% of premium) has what appears to be a greater dollar amount of impact proportionally than the elimination of one-life groups

The purpose is to study the ability of three technical earnings forecasting methods (smoothing, random walk and cross-section) to reflect Tunisian stock market expectations

WETTABILITY OF GRAPHITIC MATERIALS AND DEVELOPMENT OF GRAPHENE LAYER AS BARRIERS TO PREVENT THE SURFACE DEGRADATION INDUCED

There is no significant relationship among investors’ perceptions based on gender, age, education, occupation and income on different avenues of investments like equity,

The End of Traditional Client Profiles/Categories From Age Income Assets Occupation Gender Family Individuals Lifestyles Personality Traits Beliefs Experiences To.. The three

 WA Police (for public interface) and DFES (for Dangerous Goods issues) for Emergency Situation or State of Emergency State Emergency Management Plan for