Profiler Instrumentation Using Metaprogramming Techniques
1. Profiler Instrumentation Using
Metaprogramming Techniques
Ritu Arora, Yu Sun, Zekai Demirezen, Jeff Gray
University of Alabama at Birmingham
{ritu, yusun, zekzek, gray}@cis.uab.edu
ACM Southeast Conference,
Auburn, Alabama
29th March 2008 Software Composition and Modeling Laboratory
SoftCom
This project is supported by NSF CAREER award (CCF-0643725)
1
Department of Computer and Information Sciences
University of Alabama at Birmingham
2. Overview of Presentation
Metaprogramming
OpenJava
Profiler
Overview of Javassist
Techniques
Profiler
AOP
Instrumentation
Discussion
2
3. Metaprogramming
• A metaprogram manipulates another program
• Main approaches towards metaprogramming
– Compile-time metaobjects
– Load-time class adaptation
– Aspect-Oriented Programming (AOP)
5. Load-Time Class Adaptation
... ... ... ... ... ...
loaded by
Inapplicable to
Application
classes loaded by
Classes Interception
Application
other class loaders
class loader class loader/Javassist
subclasses of
Portable interception
of all application
JMangler:
classes
Class
Java extension of
ClassLoader
APIs ClassLoader
Native extension of
Bootstrap
bootstrap CL
class loader
Java
Virtual
Dependent on
Machine
custom JVM
Execution engine
implementation
Dependent on
I/O interface
Native platform specific
Native I/O DLL
DLL
libraries
custom DLL
6. Aspect-Oriented Programming
• Language-based approach for capturing
crosscutting concerns
• A concern is crosscutting if it is scattered across
multiple modules
• Example of an AOP Language: AspectJ
7. Crosscutting Concern
XML Parsing in Apache
Tomcat Server
Logging in Apache
Tomcat Server
Source: http://www.parc.com/research/projects/aspectj/
8. Case Study: Profiler Instrumentation
• Essential tool for
code optimization
and performance
enhancement
• Provides the run-
time information
about the code
• Commercial
Profiler: JProbe
10. Profiler Implementation Using
OpenJava
public class ProfilerMeta instantiates Metaclass
extends OJClass{
// Show Profiler in main method
public void translateDefinition() throws MOPException {
if(m.getName().equalsIgnoreCase(quot;mainquot;))
OJMethod[] methods = getDeclaredMethods();
OJMethod m; // each method in application
Statement showGUI =
int msize; // number of statements in method
makeStatement(quot;{Profiler.show();}quot;);
for (int i = 0; i < methods.length; ++i) {
public class ProfilerMeta
m m.getBody().insertElementAt(showGUI, 0);
= methods[i];
instantiates Metaclass
// Show Profiler in main method
if(m.getName().equalsIgnoreCase(quot;mainquot;))
// Insert Profiler.start() at method front
extends OJClass{
Statement showGUI =
Statement start =
makeStatement(quot;{Profiler.show();}quot;);
OJMethod[] methods = getDeclaredMethods();
m.getBody().insertElementAt(showGUI, 0);
makeStatement(quot;{Profiler.start(quot;quot; +
OJMethod m; // each method in application
// Insert Profiler.start() at method front
m.getName() + quot;quot;);}quot;);
int msize; // number of statements in method
Statement start =
m.getBody().insertElementAt(start, 0);
makeStatement(quot;{Profiler.start(quot;quot; +
m.getName() + quot;quot;);}quot;);
m.getBody().insertElementAt(start, 0);
//Insert Profiler.end() at method end at method end
Insert Profiler.end()
//
Statement end =
Statement end =
makeStatement(quot;{Profiler.end();}quot;);
makeStatement(quot;{Profiler.end();}quot;);
m.getBody().insertElementAt(end, msize);
m.getBody().insertElementAt(end, msize);
}
}
}
11. Profiler Implementation Using
Javassist
public class ProfilerClassLoader
extends ClassLoader {
public Class loadClass(String arg0)
throws ClassNotFoundException {
CtMethod m = methods[i];
CtClass c = ClassPool.getDefault().get(arg0);
CtMethod[] methods = c.getDeclaredMethods();
if(m.getName().equalsIgnoreCase(quot;mainquot;))
for (int i = 0; i < methods.length; i++) {
m.insertBefore(quot;new Profiler.show();quot;);
CtMethod m = methods[i];
if(m.getName().equalsIgnoreCase(quot;mainquot;))
m.insertBefore(quot;new Profiler.show();quot;);
m.insertBefore(quot;Profiler.start(” +
CtClass c = ClassPool.getDefault().get(arg0);
m.insertBefore(quot;Profiler.start(” +
m.getName() + quot;quot;);quot;);
m.getName() + quot;quot;);quot;);
CtMethod[] methods = c.getDeclaredMethods();
m.insertAfter(quot;Profiler.end();quot;; +
m.insertAfter(quot;Profiler.end();quot;; +
}
return c.toClass();
}
}
12. AspectJ
• A crosscutting concern is isolated in a modular
unit called “aspect”
• Like classes, aspects contain attributes and
methods and can inherit from other aspects
• Aspects are woven into the application at the
compile-time via AspectJ compiler
• Key language concepts: joint point, pointcut
expression, advice
14. Benefits and Limitations of Using
OpenJava
• Clear modularization boundary
– Separate base program and the metaprogram
– Changes can be made to any line of Java code
• Problem
– Definition of each class in the source file must add
“instantiates <metaclass-name>”
– It cannot automatically catch every return point for each
method
– It cannot find the return statement nested in a statement
or a block
• Solution: parse the code within the OpenJava
metaprogram
15. Expressiveness of AspectJ
• AspectJ is more expressive than OpenJava and
Javassist
• Code written in AspectJ is easier to read and
comprehend
• Integrated tool support for AspectJ
• Limitation
– Need to recognize and specify join points clearly
– Certain code constructs like “for loops” cannot be
specified as join points
16. Javassist as a ByteCode
Transformation API
• Source code not required if the bytecode level
APIs are used
• Does not need any special compiler
• Transformations can be performed at both
compile-time and load-time
• Limitation
– Inapplicable to classes loaded by other class
loaders
17. Conclusion
• Manual invasive changes to a source code base
is challenging
• Metaprogramming can help in isolating change
requests in separate modules without the need
of invasively changing the source code
Source for profiler: http://www.filebuzz.com/software_screenshot/full/4146-LTProf.gif
- Source program (written in OpenC++ or OpenJava) is translated into top-level definitions for classes and member-functions.A metaobject is created for each top-level definition.metaobject then translates the top-level definitions into appropriate C++ or Java codeTranslated code is then collected and assembled into a contiguous source code. <number><number>
Achieved by customizing the Java class loaderi.e., through bytecode manipulation Can be used to modify the structure and behavior of the classExample: Javassist APIsFour ways of intercepting classes at load-time: use of a custom class loader, extension of the class java.lang.ClassLoader, use of a custom JVM implementation, and use of a custom I/O DLL. Only the second option provides portable generic interception.
-red shows lines of code that handle logging in org.apache.tomcat server-not in just one place-not even in a small number of places<number>
<number>
Supports structural reflectionAbility to alter the structure of existing classesNew classes can be definedByte-code can be transformed at either the load-time or compile-time<number>