Section 31.4. MEETING APPLICATION-AWARENESS REQUIREMENTS WITH PROSE


31.4. MEETING APPLICATION-AWARENESS REQUIREMENTS WITH PROSE

To show that dynamic AOP can be used for expressing application awareness, we developed PROSE (PROgrammable extenSions of sErvices), a system in which aspects are first-class Java entities and all related constructs are expressed using the base language, Java. The first version of PROSE was based on the debugger interface of the JVM [21]. The second version [19] is a JIT-based stub weaver based on IBM's Jikes Research Virtual Machine [1]. The PROSE experience has shown that dynamic AOP can be efficient and can be provided at a low implementation cost. In addition, by carefully selecting the features of the dynamic AOP platform, one can fully address the requirements of application awareness. The next section gives an overview of this system.

31.4.1. Addressing Application Awareness in PROSE

31.4.1.1 Addressing Security

For application awareness, security is a very important feature. Just like Internet browsers that control the code they download from the network, the AOP support embedded in each node must guarantee that a foreign advice cannot damage the local system. In this respect, stub weavers offer a better choice than advice weavers. The reason is that a full-code weaver mixes advice and base code, and this makes the verification of the code origin at a later point in time a difficult task. By contrast, stub weavers separate advice code from the base code. This way, the advice code (potentially originating from a foreign host) can be kept in a sandbox. This setup allows well-understood security models (such as the Java Security Model [31]) to be enforced. It was for this reason that we have chosen the stub-weaver approach for PROSE.

31.4.1.2 Addressing Performance

Under normal operations (no woven aspects), the dynamic weaving platform should not lead to significant performance degradation (performance is a key requirement when dealing with online and mobile systems). Our decision to implement PROSE using a JIT-time approach was based on measurements using SpecJVM [27] and JavaGrande [8] benchmarks. The results are summarized in Table 31-2. They show that a JIT-time weaver slows down application execution less than 10% when considering all field operations and method calls as join points. The good performance of a JIT-time weaver was to be expected, as native code hooks can be programmed extremely efficiently. According to our measurements [20], JIT-time weavers compare favorably with load-based approaches, which incur larger overheads at each join point. With a JIT-time weaver, we also obtained encouraging results when expressing CPU-intensive adaptations like orthogonal persistence and transactional processing [18].

Table 31-2. Relative Overhead with AOP Support for Method Boundaries, Field Sets, and Field Gets

Benchmark

 

Relative Overhead

 

Java Grande Benchmark Suite

 

LUFact:Kernel

 

103.15 %

Crypt:Kernel

 

103.24 %

SOR:Kernel

 

98.74 %

SparseMatmult:Kernel

100.23 %

Average

 

101.44 %

 

SPECjvm 98 Benchmark Suite

 

check

 

103.04 %

jess

 

110.19 %

db

 

105.17 %

jack

 

107.84 %

javac

 

113.51 %

Average

 

107.95 %


31.4.1.3 Addressing Portability and Cost

The advantage of a small performance overhead (mainly due to the efficiency of native code) is balanced by the disadvantage of a reduced portability. By contrast, load-time stub weavers are usually portable from one JVM to another, as they are essentially replacements for a standard JVM classloader component. To address this restriction, we divided the AOP support provided in PROSE into two modules.

31.4.2. PROSE Architecture

System modules. The AOP engine is a replaceable module that uses the support for weaving provided by the execution monitor, a module that is tightly integrated with the JVM and its JIT compiler.

Figure 31-4 gives an overview of this architecture. In the upper layer, the AOP engine accepts aspects (1) and transforms them into basic entities like join point stop requests (2). It activates the stop requests by invoking methods of the execution monitor (3). The execution monitor is integrated with the JVM. When the execution reaches one of the activated join points, the execution monitor notifies the AOP engine (4), which executes an advice (5).

Figure 31-4. PROSE architecture.


Following a conventional design approach, we kept in the execution monitor only the most frequently used functionality. Our goal was to show that this functionality can be provided at a low (implementation) cost. Indeed, in our first prototype, the execution monitor consisted of only 1600 lines of code added to the JVM core. If this support were available in every JVM platform, application providers could program their own AOP engines on top of the execution monitor.

The execution monitor. The execution monitor support is integrated with the JVM. It contains the functionality for activating join points (used when a new aspect is added to the system) and the callback functionality for notifying the AOP engine that a join point has been reached (used at runtime).

When a new aspect is added to the system, the AOP engine activates join points using the join point activation API of the execution monitor. It specifies as parameter a class member (e.g., field or method) that uniquely identifies the join point to be activated. When an activated join point is reached, the execution monitor notifies through the callback API the AOP engine (each AOP engine implements an appropriate interface) by passing a join point object to the AOP engine.

The passed join point object contains methods for the inspection of local variable values, of thread states, of return values, etc. This design implies making the stack layout visible to the join point object passed to the aspect engine. This is needed because the join point interface allows gathering information of the local environment (e.g., local variables).

Stack visibility is just one of the problems that must be solved when providing an execution monitor. For consistency and efficiency reasons, a tight integration of the execution monitor with several components of the JVM is needed.

One example is the division of a method's body into basic blocks. A basic block is a code sequence in which the stack layout remains unchanged. Basic blocks are used by the garbage collector to inspect the stack and to collect object references. When adding join point stubs, a method call may occur at a location where no basic block boundary was detected during bytecode analysis. As a consequence, JIT-level AOP implies the additional cost of adapting the bytecode analyzer of the JVM. In general, all information related to join points must be as close as possible to the internal representation in the JVM.

The AOP engine. The main functions of the AOP engine are (1) to decompose an aspect into stop requests and to activate corresponding join points, and (2) to execute a corresponding advice when an active join point is reached. By replacing the AOP engine, one can define an alternative AOP platform, which may differ from PROSE in various ways.

We explain the general architecture of the AOP engine by illustrating the actions for weaving an aspect using PROSE. Then we show the actions taken to execute the corresponding advice. Our example aspect definition encrypts all bytes-array parameters passed to sendBytes-methods. We use PROSE to describe this aspect:

 (1) // before methods 'void *.sendBytes(byte[] x)' (2) // do encrypt(x) (3) class ExampleCut extends BeforeCut { (4) void sendBytes(ANY thisObject, byte[] x) (5)          { encrypt(x); } (6) } 

To weave this aspect, the AOP engine performs several sub-tasks, as illustrated in Figure 31-4. First, it inspects all the classes currently loaded by the JVM and gathers all methods m1 . . . mn that match the signature '*.sendBytes(byte[] x)'. For all generated stop requests, it activates method entry join points using the join point activation API of the underlying execution monitor.

Upon entry in m1 . . . mn, the execution monitor calls the AOP engine. The AOP engine guarantees that all run-time conditions defining the reached join point are met (e.g., the aspect may be defined using control-flow crosscutting mechanisms [4]). If all the dynamic checks are passed successfully, the advice can be executed. Finally, the AOP engine executes the encrypt method. If classes are loaded by the JVM at a later point in time, the actions done for aspect weaving are repeated accordingly on each new class in the system.



Aspect-Oriented Software Development
Aspect-Oriented Software Development with Use Cases
ISBN: 0321268881
EAN: 2147483647
Year: 2003
Pages: 307

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net