Runtime Aspect Weaving Through Metaprogramming Jason Baker and Wilson Hsieh Handi-Wrap
Tightly integrated Java extension First-class advice objects ( Wrappers ) Weaving performed at runtime Implemented in the Maya syntax extension system
Problem: Caching Independent reuse of: –caching implementation –caching policy: shared, per-instance, single instance, others? –actual binding of method name
Advantages First-class advice increases reuse –Object composition –Explicit constructor parameters –Member and local advice Dynamic weaving also brings –Advice on libraries without source code –Less recompilation
Features Extends Java declaration, statement, and expression syntax Provides first-class notion of wrappers and procedures Hides an efficient calling convention through metaprogramming Supports binary libraries through bytecode rewriting
Wrappers and Procedures applying a wrapper to a method creates a procedure M W P
Wrappers and Procedures applying a wrapper to a method creates a procedure calls now go through the procedure
Wrappers and Procedures applying a wrapper to a method creates a procedure calls now go through the procedure each application creates a new procedure
Example: Caching Count redundant calls through tracing aspect Discover interactions between caches Does caching fit method semantics? Consider a class path search routine –compilers need caching –conventional class loaders don’t benefit –plugin loaders must not cache
Tracing a Method Let’s examine the arguments to a static method, ClassPath.lookup() ClassPath.Rsc wrapper lt(String name) { System.out.println(“lookup “ + name); return wrapped.apply(name); }; wrap ClassPath.lookup(String) with lt;
Wrapper Arguments Argument types are invariant Polymorphic arguments defined with Any type Wrappers may accept a variable number of arguments through rest array Type checking is in general dynamic
Reusable Wrappers General-purpose wrappers provided in maya.wrap.Wrappers tracer similar to lt, but takes any number of arguments, and returns any type wrap ClassPath.lookup(String) with Wrappers.tracer;
Wrapping Details Methods are advised by Wrapper instances Procedure objects represent method and wrapper bodies Generator takes an original method Procedure, and returns a wrapped Procedure
Composable Wrappers Explicitly use generator for greater flexibility CacheNth – caches return value based on n th argument makePerInstance – Generate and call through argument wrapper for each receiver instance makeConditionalWrapper – Call through wrapper based on boolean Procedure
Composing Caches We can build a lookup cache for each ClassPath instance cacheFirst avoids array overhead of CacheNth(1) wrap ClassPath.lookup(String) with Wrappers.makePerInstance(new CacheNth(1));
Composing Caches or one instance, using makeConditionalWrapper() final ClassPath p = new ClassPath(); wrap ClassPath.lookup(String) with makeConditionalWrapper( new boolean procedure(ClassPath r, String _) { return r == p; }, cacheFirst);
Performance Static transformation and dynamic code generation Avoids Java reflection API Efficient calling convention –avoids array allocation when possible –avoids allocating small integers
Interposing on Methods Each class includes Procedure[] Each method body calls through corresponding slot when non-null Innermost wrapper calls original method definition through Procedure object –method duplicated statically –Procedure subclass generated dynamically
Rewrite Overhead
Caching Performance
Related Work Reuse –Hanenburg and Unland [OOPLSA-ASC01] Dynamic weaving –JAC [Reflection 01] –David et al. [OOPSLA-ASC01] Separate compilation –Aspectual Components [?] –XOTCL [?]
Conclusions First-class advice is reusable –Application-specific cache policies built from reusable wrappers Binary libraries need advice –ClassPath cache useful to compiler Dynamic weaving can be efficient
Discussion Handi-Wrap