SM JavaOne 2004 Bytecode Instrumentation – Making It Simple Session 3042 Joseph Coha and David Seidman Enterprise Java Lab Hewlett Packard Company www.hp.com/go/java 1 | 2004 JavaOneSM Conference | Session 3042 Copyright Hewlett Packard Co., 2004.
Goals of Bytecode Instrumentation BOF Learn from our experience implementing and using bytecode instrumentation (BCI) Use BCI as a tool to understand your application Provide an environment for you to share your experiences with BCI! | 2004 JavaOneSM Conference | Session 3042 2 Copyright Hewlett Packard Co., 2004.
Agenda What is bytecode instrumentation? Class file format What’s hard about implementation? Examples of how it’s done Transformations Selecting methods to instrument Collecting the data Experience Summary | 2004 JavaOneSM Conference | Session 3042 3 Copyright Hewlett Packard Co., 2004.
Bytecode instrumentation • Modification of the class file content • Based on early object code modification work • Applied to Java™ as bytecode manipulation ─ Support for optimization, generics, AOP, … ─ JVM™ hooks: -Xprep, preprocessor as a property ─ Special class loader hooks • Java Virtual Machine Tools Interface (JVMTI) ─ Includes callback mechanism for class loading ─ Enables bytecode instrumentation ─ JVMTI (JSR 163) in J2SE 5.
Publicly Available BCI Tools • ASM: ObjectWeb Consortium – __asm__ • BCEL: Apache – Bytecode Engineering Library • BIT: University of Colorado – Bytecode Instrumenting Tool • • • • • • Javassist: JBoss – Java Programming Assistant java_crw_demo: J2SE 5.0 JVMTI class load jclasslib: JProfiler – ej-technologies JikesBT: IBM – Jikes Bytecode Toolkit JOIE: Duke University Others … | 2004 JavaOneSM Conference | Session 3042 5 Copyright Hewlett Packard Co., 2004.
Products Using BCI • • • • Wily Technology – Introscope HP – OpenView Transaction Analyzer (OVTA) AdventNet – JMX + BCI Eclipse ─ JUnit ─ Profiler • AOP: AspectJ, AspectWerkz • Most Java profilers: JProbe, Optimizeit, JProfiler, … | 2004 JavaOneSM Conference | Session 3042 6 Copyright Hewlett Packard Co., 2004.
The Java Class File – Constant Pool cp_info { u1 tag; u1 info[]; } Header Constant Pool CONSTANT_Methodref_info { u1 tag; u2 class_index; u2 name_and_type_index; } Access Flags, this, super Implemented Interfaces Fields CONSTANT_NameAndType_info { u1 tag; u2 name_index; u2 descriptor_index; } Constant Type CONSTANT_Utf8_info { u1 tag; u2 length; u1 bytes[length]; } Methods Class Attributes | 2004 JavaOneSM Conference | Session 3042 7 Class 3 Fieldref 5 Methodref 5 InterfaceMethodref 5 String
The Java Class File – Methods Header Constant Pool Access Flags, this, super Implemented Interfaces Fields Methods Class Attributes | 2004 JavaOneSM Conference | Session 3042 8 method_info { u2 access_flags; u2 name_index; u2 descriptor_index; u2 attributes_count; attribute_info attributes[attributes_count]; } code_attribute { u2 attribute_name_index; u4 attribute_length; u2 max_stack; u2 max_locals; u4 code_length; u1 code[code_length]; u2 exception_table_length; { u2 start_pc; u2 end_pc; u2 handler_pc
Bytecode Instructions Interesting instructions and their side-effects • Control flow ─ ─ goto, jsr, ret, if*, *cmp*, athrow Table jumping: lookupswitch, tableswitch ─ Challenging because of the jump table representation ─ • Method invocation ─ ─ • Impact the stack size Type conversions and checks ─ • get/put field and static Arithmetic operations ─ • Push, pop, dup, load, *load, *store, … max_stack must be updated with control flow information after traversal of the basic blocks Field access ─
BCI Transformations • Transformation target ─ Whole program ─ Selective ─ Class ─ Method • Transformation time ─ Ahead-of-time or static ─ At run-time ─ Load time ─ Arbitrary time – Requires class loader interaction (pre 5.0) – RedefineClasses() in 5.0 • Transformation types ─ Replacement ─ Insertion ─ Deletion | 2004 JavaOneSM Conference | Session 3042 10 Copyright Hewlett Packard Co., 2004.
Parsing the Class File • Goal: Rapid parsing and low memory usage • Methods: ─ Ad hoc ─ Intermediate representation (IR) ─ Abstraction of class file elements ─ All elements as objects: BCEL – Fly weight constants for immutables (stack ops) ─ Lightweight alternatives – Visitor pattern for simple transformations: ASM • Must provide good public interface for chosen audiences ─ BCEL targets bytecode experts ─ Javassist targets Java programmers | 2004 JavaOneSM Conference | Session 3042 11 Copyright Hewlett P
BCEL UML Overview JavaClass and Code details | 2004 JavaOneSM Conference | Session 3042 12 Copyright Hewlett Packard Co., 2004. From Dahm, et. al.
Agenda What is bytecode instrumentation? Class file format What’s hard about implementation? Examples of how it’s done Transformations Selecting methods to instrument Collecting the data Experience Summary | 2004 JavaOneSM Conference | Session 3042 13 Copyright Hewlett Packard Co., 2004.
What’s Hard? • Creating an intermediate form ─ Deserialization ─ All objects as intermediate representation ─ Less costly alternatives – bookeeping overhead ─ Size of intermediate representation • Apply multiple transformations ─ May require update to abstract representation with each change ─ Look for rewind() methods • Keeping the class file verifiable ─ Consistency ─ Size | 2004 JavaOneSM Conference | Session 3042 14 Copyright Hewlett Packard Co., 2004.
What’s Hard? • Class Pool size bloat ─ “Dead entry” elimination requires whole class analysis • Method size bloat ─ Multiple return points • Exception unwinding through frames ─ Keeping entry/exit data consistent • Instrumenting classes early – BCI in Java • Making BCI work – Debugging BCI written in C | 2004 JavaOneSM Conference | Session 3042 15 Copyright Hewlett Packard Co., 2004.
What’s Hard? • Making BCI fast ─ Required for adaptive profiling systems • Inserting correct instrumentation ─ Correctness ─ Verification ─ Consistency: max stack, max locals, sizes, … • Thread safety ─ Race conditions ─ Deadlocks • “Stale” frames when re-instrumenting | 2004 JavaOneSM Conference | Session 3042 16 Copyright Hewlett Packard Co., 2004.
Creating Instrumentation Hooks (pre-5.0) • Experience with BCEL and class loaders [McPhail] • Custom class loader ─ Finds, instruments, and loads class before system class loader ─ System classes (java.* and javax.
Agenda What is bytecode instrumentation? Class file format What’s hard about implementation? Examples of how it’s done Transformations Selecting methods to instrument Collecting the data Experience Summary | 2004 JavaOneSM Conference | Session 3042 18 Copyright Hewlett Packard Co., 2004.
BCI Instrumentation • Traversal of elements • Filter that selects instrumentation site • Generator inserts transformation | 2004 JavaOneSM Conference | Session 3042 19 Copyright Hewlett Packard Co., 2004.
Approaches for Method Instrumentation • Rename ─ Entry point renamed • Wrap ─ Original method’s name ─ Add instrumentation ─ Call original target method • Insert ─ Directly modify the method/class • Mixin ─ Add field, interface, method to class ─ Add prefix/suffix to method(s) | 2004 JavaOneSM Conference | Session 3042 20 Copyright Hewlett Packard Co., 2004.
JRat (BCEL-based) jrat.sourceforge.net public class MyMath { public int max(int a, int b) { return (a > b) ? a : b; } } public class MyMath { static final MethodHandler HANDLER_FOR_max_0 = HandlerFactory.getMethodHandler( "org.package.MyMath", "max", "(II)I"); private final int max__shiftone_JRat(int a, int b) { return (a > b) ? a : b; } public int max(int a, int b) { long start = 0L; Object args[] = null; boolean success = false; try { HANDLER_FOR_max_0.onMethodStart(this, args); start = System.
java_crw_demo BCI Library • C library in 5.0 JRE used by HPROF and other JVMTI agents • BCI support: [O’Hair] ─ Class initialization ─ Entry to the java.lang.Object init method (signature "()V") ─ Inject invokestatic call to tclass.obj_init_method(object) ─ Method instrumentation ─ Entry – Inject invokestatic call to tclass.call_method(class_num,method_num) – Map the class_num and method_num using the crw library ─ Return (each site) – Inject invokestatic call to tclass.
java_crw_demo BCI Library • Non-instrumented methods ─ ─ ─ ─ init methods finalize methods whose length is 1 "system" classes clinit methods java.lang.Thread.
java_crw_demo Example: Constant Pool Addition • fillin_cpool_entry ─ Write the information as a constant pool entry • add_new_cpool_entry ─ Call to fillin_cpool_entry • add_new_method_cpool_entry ─ ─ ─ ─ Call to add UTF8 name to constant pool Call to add UTF8 descr index to constant pool Call to add name type to constant pool Call to add method type to constant pool • cpool_setup (index 0 not in pool) ─ add_new_method_cpool_entry • inject_class ─ cpool_setup | 2004 JavaOneSM Conference | Session 3042 2
Add the runtime tracking method to the Constant Pool static CrwCpoolIndex add_new_method_cpool_entry(CrwClassImage *ci, CrwCpoolIndex class_index, const char *name, const char *descr) { CrwCpoolIndex name_index, descr_index, name_type_index; name_index = add_new_cpool_entry(ci, JVM_CONSTANT_Utf8, len, 0, name, len); descr_index = add_new_cpool_entry(ci, JVM_CONSTANT_Utf8, len, 0, descr, len); name_type_index = add_new_cpool_entry(ci, JVM_CONSTANT_NameAndType, name_index, descr_index, NULL, 0); return add_n
java_crw_demo Example: Injection at Method Entry • injection_template ─ Insertion of the actual bytecodes • entry_injection_code - create injection code at entry to a method ─ injection_template • method_inject_and_write_code ─ entry_injection_code ─ Write bytecode image • method_write_bytecodes ─ method_inject_and_write_code ─ Adjust all offsets: ─ Code length ─ Maximum stack ─ Exception table ─ Code attributes ─ Attribute length | 2004 JavaOneSM Conference | Session 3042 26 Copyright Hewlett Packard C
Generating the bytecodes static ByteOffset injection_template(MethodImage *mi, ByteCode *bytecodes, ByteOffset max_nbytes, CrwCpoolIndex method_index) { max_stack = mi->max_stack + 2; nbytes += push_pool_constant_bytecodes( bytecodes+nbytes, ci->class_number_index); nbytes += push_short_constant_bytecodes( bytecodes+nbytes, mi->number); bytecodes[nbytes++] = (ByteCode)opc_invokestatic; bytecodes[nbytes++] = (ByteCode)(method_index >> 8); bytecodes[nbytes++] = (ByteCode)method_index; bytecodes[nbytes] = 0; /
Using java_crw_demo(): 19 Parameters 1. Caller assigned class number for class 2. Internal class name • Example: java/lang/Object (use “/” separator) 3. Pointer to class file image for the class 4. Length of the class file in bytes 5. Set to 1 if this is a system class • Prevents injections into empty , finalize, and methods 6. Class that has methods to call at the injection sites (tclass) 7. Signature of tclass • Format: "L" + tclass_name + ";" 8.
Using java_crw_demo 10. Method name in tclass to call at all return opcodes in every method 11. Signature of the method • Format: "(II)V" 12. Method name in tclass to call when injecting java.lang.Object. 13. Signature of the method • Format: "(Ljava/lang/Object;)V" 14. Method name in tclass to call after every newarray opcode in every method 15. Signature of the method • Format: "(Ljava/lang/Object;II)V" 16. Returns a pointer to new class file image 17. Returns the length of the new image 18.
java_crw_demo parameters JNIEXPORT void JNICALL java_crw_demo( unsigned class_number, const char *name, const unsigned char *file_image, long file_len, int system_class, char* tclass_name, char* tclass_sig, char* call_name, char* call_sig, char* return_name, char* return_sig, char* obj_init_name, char* obj_init_sig, char* newarray_name, char* newarray_sig, unsigned char **pnew_file_image, long *pnew_file_len, FatalErrorHandler fatal_error_handler, MethodNumberRegister mnum_callback ); | 2004 JavaOneSM Confe
Start-up Using JVMTI • Start-up ─ -agentlib:= ─ Agent_OnLoad() called when library loaded ─ Set-up the callbacks jvmtiEventCallbacks callbacks; Callbacks.
Class file load callback static void JNICALL cbClassFileLoadHook(jvmtiEnv *jvmti_env, JNIEnv* env, jclass class_being_redefined, jobject loader, const char* name, jobject protection_domain, jint class_data_len, const unsigned char* class_data, jint* new_class_data_len, unsigned char** new_class_data){ if ( gdata->bci_counter == 0 ) { class_prime_system_classes(); } gdata->bci_counter++; Generating the class index ClassIndex cnum; loader_index = loader_find_or_create(env,loader); if ( class_being_redefined
Call BCI library to instrument ((JavaCrwDemo)(gdata->java_crw_demo_function))( cnum, name, class_data, class_data_len, system_class, "sun/tools/hprof/Tracker", Class with method "Lsun/tools/hprof/Tracker;", "CallSite", Method to call "(II)V", NULL, NULL, NULL, NULL, NULL, NULL, &new_image, &new_length, &my_crw_fatal_error_handler, &class_set_methods); | 2004 JavaOneSM Conference | Session 3042 33 Copyright Hewlett Packard Co., 2004.
Return the new class file if ( new_length > 0 ) { unsigned char *jvmti_space; jvmti_space = (unsigned char *) jvmtiAllocate((jint)new_length); (void)memcpy((void*)jvmti_space, (void*)new_image, (int)new_length); *new_class_data_len = (jint)new_length; *new_class_data = jvmti_space; } else … | 2004 JavaOneSM Conference | Session 3042 34 Copyright Hewlett Packard Co., 2004.
Agenda What is bytecode instrumentation? Class file format What’s hard about implementation? Examples of how it’s done Transformations Selecting methods to instrument Collecting the data Experience Summary | 2004 JavaOneSM Conference | Session 3042 35 Copyright Hewlett Packard Co., 2004.
Selecting Methods: Constraints • Depends on nature of BCI library ─ May be circular dependencies with Java library • Load-time instrumentation problem ─ JVMPI ─ Java-based BCI cannot instrument classes it uses • Non-issue with static instrumentation • Dynamic instrumentation adds significant flexibility ─ Classes can be redefined after they are first used | 2004 JavaOneSM Conference | Session 3042 36 Copyright Hewlett Packard Co., 2004.
Selecting Methods: Functional Goals • Depends on technical demands • Transaction measurement tool may only instrument top-level J2EE invocations • Development-time profiler may only instrument user-level code ─ Filter out app server code ─ Filter out third party code • AOP tool may instrument very selectively in arbitrary ways ─ Special logging ─ Special debug support | 2004 JavaOneSM Conference | Session 3042 37 Copyright Hewlett Packard Co., 2004.
Selecting Methods: Performance • Usually better to increase instrumentation-time overhead and decrease steady-state overhead • Many filtering opportunities ─ ─ ─ ─ Accessor methods Other small methods 3rd party code Well-understood, application-specific code • Make most expensive instrumentation conditional, collect samples • Optimize injected code aggressively | 2004 JavaOneSM Conference | Session 3042 38 Copyright Hewlett Packard Co., 2004.
Selecting Methods: New Opportunities • JVMTI and JPLIS open up staged instrumentation • Make conservative decisions initially • Remove or add instrumentation as data is collected and application understood • Many adaptive opportunities ─ More efficient profiling ─ Targeted optimizations ─ Find and repair bugs on the fly | 2004 JavaOneSM Conference | Session 3042 39 Copyright Hewlett Packard Co., 2004.
Agenda What is bytecode instrumentation? Class file format What’s hard about implementation? Examples of how it’s done Transformations Selecting methods to instrument Collecting the data Experience Summary | 2004 JavaOneSM Conference | Session 3042 40 Copyright Hewlett Packard Co., 2004.
Approaches for Data Collection • C heap data structures ─ Requires call to native code from Java • Java heap ─ Measurement data structures interfere with program • Files ─ I/O can be slow, even with buffering • • • • Pipes Sockets/Network RMI, RMI/SSL JMX | 2004 JavaOneSM Conference | Session 3042 41 Copyright Hewlett Packard Co., 2004.
Efficient Collection • Minimize method calls ─ ─ ─ ─ Finding class and method names Thread information Native calls Cross language calls • Keep critical sections short • Use thread local storage to avoid contention ─ Global data structures need locks | 2004 JavaOneSM Conference | Session 3042 42 Copyright Hewlett Packard Co., 2004.
Efficient Collection • Persist data that will no longer be modified ─ Data from thread that has exited can be written to file • Long term collection ─ Minimize total amount of data collected ─ Toggle on/off ─ Sample ─ Filter | 2004 JavaOneSM Conference | Session 3042 43 Copyright Hewlett Packard Co., 2004.
JikesBT – Integrated into Eclipse • Profiling and display of information | 2004 JavaOneSM Conference | Session 3042 44 Copyright Hewlett Packard Co., 2004.
Agenda What is bytecode instrumentation? Class file format What’s hard about implementation? Examples of how it’s done Transformations Selecting methods to instrument Collecting the data Experience Summary | 2004 JavaOneSM Conference | Session 3042 45 Copyright Hewlett Packard Co., 2004.
BCI in action Using J2SE 5.0 java.lang.instrument 46 | 2004 JavaOneSM Conference | Session 3042 Copyright Hewlett Packard Co., 2004.
java.lang.instrument | 2004 JavaOneSM Conference | Session 3042 47 Copyright Hewlett Packard Co., 2004.
Start-up: java.lang.instrument • Support for Agents (J2SE 5.0 beta 2) ─ -javaagent:classname=options ─ classname required to have method premain ─ public static void premain(String agentArgs, Instrumentation inst); ─ premain() called before application main() • Interfaces ─ ClassFileTransformer ─ Instrumentation: Services needed to instrument • Classes ─ ClassDefinition ─ Parameter to Instrumentation.redefineClasses method | 2004 JavaOneSM Conference | Session 3042 48 Copyright Hewlett Packard Co.
Start-up: java.lang.instrument • Support for Agents (J2SE 5.0) [Bateman] ─ -javaagent:jarfile=options ─ jarfile meta information specifies method to call ─ Premain-Class: ─ Boot-Class-Path: ─ Can-Redefine-Classes: | 2004 JavaOneSM Conference | Session 3042 49 Copyright Hewlett Packard Co., 2004.
BCEL [Dahm, et. al.] | 2004 JavaOneSM Conference | Session 3042 50 Copyright Hewlett Packard Co., 2004.
Interface ClassFileTransformer byte[] transform( ClassLoader loader, // null if system String className, // java/util/List Class> classBeingRedefined, // null if not ProtectionDomain protectionDomain, byte[] classfileBuffer) // input class file throws IllegalClassFormatException • Returns null if no modifications made • New class definition: ClassLoader.defineClass • Redefinition: Instrumentation.redefineClasses | 2004 JavaOneSM Conference | Session 3042 51 Copyright Hewlett Packard Co., 2004.
Interface Instrumentation void addTransformer( ClassFileTransformer transformer) boolean removeTransformer( ClassFileTransformer transformer) void redefineClasses( ClassDefinition[] definitions) throws ClassNotFoundException,UnmodifiableClassException Class[] getAllLoadedClasses() … | 2004 JavaOneSM Conference | Session 3042 52 Copyright Hewlett Packard Co., 2004.
Dynamic BCI Start-up 1. 2. 3. 4. Start java with option: -javaagent:myAgent On start-up, Java runtime calls: premain() Save object that implements Instrumentation Add the transformer ─ Called for every class loaded ─ inst.addTransformer(myTrans); | 2004 JavaOneSM Conference | Session 3042 53 Copyright Hewlett Packard Co., 2004.
MyAgent.premain() Save Instrumentation/Call addTransformer() import java.lang.instrument.*; public class MyAgent { static Instrumentation myInst; static String myArgs; static MyTransformer myTrans; public static void premain(String agentArgs, Instrumentation inst) { myInst = inst; myArgs = agentArgs; myTrans = new MyTransformer(); inst.addTransformer(myTrans); MyMonThread myMonThread = new MyMonThread(); myMonThread.start(); }| 54 2004 JavaOneSM Conference | Session 3042 Copyright Hewlett Packard Co.
Dynamic BCI Implementation of ClassFileTransformer • Input parameters ─ Classloader ─ Class name ─ Class | 2004 JavaOneSM Conference | Session 3042 55 Copyright Hewlett Packard Co., 2004.
MyTransformer.transform() public class MyTransformer implements ClassFileTransformer { public byte[] transform( java.lang.ClassLoader inLoader, java.lang.String className, java.lang.Class> classBeingRedefined, java.security.ProtectionDomain jspd, byte[] inba) throws IllegalClassFormatException { byte[] lba = inba; if ( className.equals(classToModify) ) { lba = mytransform(className, methodName); } return lba; } | 2004 JavaOneSM Conference | Session 3042 56 Copyright Hewlett Packard Co., 2004.
Dynamic BCI while program is running Start with thread wake-up • Monitoring thread periodically wakes up and calls: ─ MyAgent.update() Select hot class-method to instrument ─ MyTransformer.mytransform() Add method we want to call to the Constant Pool – MyTransformer.traceMethod() Modify the bytecode of the hot method Update the max stack value Reset the Constant Pool Create new class file inst.redefineClasses(class, bytecodes) | 2004 JavaOneSM Conference | Session 3042 57 Copyright Hewlett Packard Co.
MyAgent.update() – 1 Find the class and method to instrument public static void update() { Class[] loadedClass = null; Instrumentation inst = MyAgent.getMyInst(); loadedClass = inst.getAllLoadedClasses(); Class classOfInterest = null; ClassAndMethod hotClassAndMethod = MyMon.getHotClassAndMethod(); String classToInstrument = hotClassAndMethod.
Dynamic BCI while program is running Add MyMon.countMethodEntry() to Class Pool • Monitoring thread periodically wakes up and calls: ─ MyAgent.update() Select hot class-method to instrument ─ MyTransformer.mytransform() Add method we want to call to the Constant Pool – MyTransformer.traceMethod() Modify the bytecode of the hot method Update the max stack value Reset the Constant Pool Create new class file inst.
MyTransformer.mytransform() public public static byte[] mytransform(String classToInst, String methodToInst) { try { JavaClass java_class = Repository.lookupClass(classToInst); // Add method to CP we will call from the instrumented method ConstantPool constants = java_class.getConstantPool(); cp = new ConstantPoolGen(constants); monitoringMethodToCall = cp.addMethodref("MyMon", "countMethodEntry", "(II)V"); // Select the method to instrument and find the index Method[] methods = java_class.
Dynamic BCI while program is running Modify the selected method • Monitoring thread periodically wakes up and calls: ─ MyAgent.update() Select hot class-method to instrument ─ MyTransformer.mytransform() Add method we want to call to the Constant Pool – MyTransformer.traceMethod() Modify the bytecode of the hot method Update the max stack value Reset the Constant Pool Create new class file inst.redefineClasses(class, bytecodes) | 2004 JavaOneSM Conference | Session 3042 61 Copyright Hewlett Packard Co.
MyTransformer.traceMethod() – 1 Create the instruction list private static Method traceMethod(Method m, int methodIndex) { Code code = m.getCode(); int flags = m.getAccessFlags(); String name = m.getName(); // Create instruction list to be inserted at method start. InstructionList patch = new InstructionList(); patch.append(new PUSH(cp, 0)); patch.append(new PUSH(cp, methodIndex)); patch.
MyTransformer.traceMethod() – 2 Insert the bytecodes and update stack // First let the super or other constructor be called if(name.equals("")) { for(int j=1; j < ihs.length; j++) { if(ihs[j].getInstruction() instanceof INVOKESPECIAL) { il.append(ihs[j], patch); break; } } } else { il.insert(ihs[0], patch); // Insert the instructions!! } // Update stack size if(code.getMaxStack() < 2) { mg.setMaxStack(2); } return mg.
Dynamic BCI while program is running Reset Constant Pool / Create class file • Monitoring thread periodically wakes up and calls: ─ MyAgent.update() Select hot class-method to instrument ─ MyTransformer.mytransform() Add method we want to call to the Constant Pool – MyTransformer.traceMethod() Modify the bytecode of the hot method Update the max stack value Reset the Constant Pool Create new class file inst.
MyTransformer.mytransform() Reset Constant Pool / Create class file public public static byte[] mytransform(String classToInst, String methodToInst) { try { JavaClass java_class = Repository.lookupClass(classToInst); // Add method to CP we will call from the instrumented method ConstantPool constants = java_class.getConstantPool(); cp = new ConstantPoolGen(constants); monitoringMethodToCall = cp.
Dynamic BCI while program is running MyAgent.update() to redefine class • Monitoring thread periodically wakes up and calls: ─ MyAgent.update() Select hot class-method to instrument ─ MyTransformer.mytransform() Add method we want to call to the Constant Pool – MyTransformer.traceMethod() Modify the bytecode of the hot method Update the max stack value Reset the Constant Pool Create new class file inst.
MyAgent.update() – 2 MyAgent.update() to redefine class byte[] newClass = MyTransformer.mytransform( classToInstrument, methodToInstrument); ClassDefinition cd = new ClassDefinition(classOfInterest, newClass); ClassDefinition cda [] = new ClassDefinition[1]; cda[0] = cd; try { inst.redefineClasses(cda); } catch ( ClassNotFoundException cnfe ) { } catch ( UnmodifiableClassException uce ) { } } | 2004 JavaOneSM Conference | Session 3042 67 Copyright Hewlett Packard Co., 2004.
Test environment • Goal: Count method entries for method consuming most time • Class A1 has two methods: a1() and a2() ─ Collect amount of time spent in each • Separate thread wakes up periodically ─ Switches preference for calling a1() or a2() • Thread launched from Agent ─ Periodically wakes up ─ Accesses performance information ─ Instrument the method with the highest time | 2004 JavaOneSM Conference | Session 3042 68 Copyright Hewlett Packard Co., 2004.
Output – Timing information a1() a2() MyMon.printCallNumbers: 0 0 MyMon.getHotMethod values: 790 191 Add instrumentation to: a1 MyMon.printCallNumbers: 236 0 Time in a1() higher Instrument a1() MyMon.getHotMethod values: 3666 1081 MyMon.printCallNumbers: 468 0 MyMon.getHotMethod values: MyMon.printCallNumbers: 842 200 791 210 200 822 935 0 MyMon.getHotMethod values: MyMon.printCallNumbers: 200 706 0 MyMon.getHotMethod values: MyMon.printCallNumbers: 801 992 0 MyMon.
Output – Corresponding call counts a1() a2() MyAgent.premain(): Enter MyAgent.premain(): Exit MyMonThread: Starting thread. MyMon.printCallNumbers: 0 0 Add instrumentation to: a1 MyMon.printCallNumbers: 435 0 MyMon.printCallNumbers: 861 0 MyMon.printCallNumbers: 1295 0 MyMon.printCallNumbers: 1722 0 MyMon.printCallNumbers: 1829 0 Add instrumentation to: a2 MyMon.printCallNumbers: 1842 485 MyMon.printCallNumbers: 1842 911 MyMon.printCallNumbers: 1842 1356 MyMon.printCallNumbers: 1842 1783 MyMon.
Analyzing your changes • Use the BCEL dump() method for JavaClass ─ Writes a class file to disk try { java_class.dump(java_class.getClassName() + "_0.class"); } catch (java.io.IOException jiio) { System.out.println("IO Except at dump"); } | 2004 JavaOneSM Conference | Session 3042 71 Copyright Hewlett Packard Co., 2004.
Analyzing your changes • Use javap to analyze the file created public void a1(); Code: 0: iconst_0 1: iconst_0 2: invokestatic #37; //Method MyMon.countMethodEntry:(II)V 5: ldc #5; //int 1000000 7: istore_1 … 36: return public void a2(); Code: 0: ldc #5; //int 1000000 2: istore_1 … | 2004 JavaOneSM Conference | Session 3042 72 Copyright Hewlett Packard Co., 2004.
Bytecode sequence writing • It’s easy when you use: java –jar bcel-5.1.jar org.apache.bcel.util.BCELifier A1_mod.class private void createMethod_1() { InstructionList il = new InstructionList(); MethodGen method = new MethodGen(ACC_PUBLIC, Type.VOID, Type.NO_ARGS, new String[] { }, "a1", "A1", il, _cp); InstructionHandle ih_0 = il.append(new PUSH(_cp, 0)); il.append(new PUSH(_cp, 0)); il.append(_factory.createInvoke("MyMon", "countMethodEntry", Type.VOID, newType[] { Type.INT, Type.INT }, Constants.
Agenda What is bytecode instrumentation? Class file format What’s hard about implementation? Examples of how it’s done Transformations Selecting methods to instrument Collecting the data Experience Summary | 2004 JavaOneSM Conference | Session 3042 74 Copyright Hewlett Packard Co., 2004.
Summary • BCI is powerful • BCI is accessible to everyone | 2004 JavaOneSM Conference | Session 3042 75 Copyright Hewlett Packard Co., 2004.
References • Geoff A. Cohen and Jeffrey S. Chase. An architecture for safe bytecode insertion. In Software – Practice and Experience, volume 34, pages 1-12, John Wiley & Sons, 2001. • Eric Burneton, Romain Lenglet, Thierry Coupaye. ASM: a code manipulation tool to implement adaptable systems. Adaptable and Extensible Component Systems, November, 2002. • Java 5.0 crw demo. /opt/java1.5/demo/jvmti/src/share/demo/jvmti/java_crw_demo/index.html. • John Meyer and Troy Downing.
Discussion Joseph Coha and David Seidman 77 | 2004 JavaOneSM Conference | Session 3042 Copyright Hewlett Packard Co., 2004.