Upload
hunter-mccormack
View
217
Download
1
Tags:
Embed Size (px)
Citation preview
Eclipse TPTP
TPTP Heap and Thread ProfilersHigh-level DesignRev 1.0
TPTP Heap and Thread ProfilersHigh-level DesignRev 1.0
Asaf Yaffe
July, 2006
Eclipse TPTP
Heap ProfilerHeap Profiler
Eclipse TPTP
Profiler RequirementsProfiler Requirements• Track object allocations and de-allocations
• Track GC events
• Produce heap dumps on demand
• Generate XML trace compatible with the JVMPI Heap Profiler
Eclipse TPTP
Martini RequirementsMartini Requirements• Generate the following events
– Object Alloc– Object Free– GC Start– GC Finish
• Support the following data requests– Get Object information (from an object id)– Get Class information (from a class id)– Get Reference graph for living objects (heap dump)
Eclipse TPTP
Martini Heap Events OverviewMartini Heap Events Overview• Martini uses intra-function instrumentation for generating Object Alloc
events• For all reference types except arrays, the Object Alloc event is generated
by instrumenting the constructor of the java.lang.Object class– The instrumentation code passes the newly allocated object reference to a
Java static recorder function HeapProxy.ObjectAlloc which calls back into JPI
– JPI tags the allocated object (via JVMTI) in order for the JVM to identify the object in the Object Free event
• communicated by the JVM via JVMTI
– This technique is sub-optimal but easy to implement• Selectivity is implemented on Object Alloc event rather than during instrumentation• May be optimized in future slices
• For array types, the Object Alloc event is generated by instrumenting array allocation sites (i.e., after newarray, anewarray, multianewarray)
• The instrumentation activity takes place during CLASS_LOAD_HOOK event of the java.lang.Object class or when heap events are dynamically enabled by the tool
Eclipse TPTP
The HeapProxy ClassThe HeapProxy Class• Martini has a helper HeapProxy Java class
– Resides in a directory that is added to the JVM boot CLASSPATH during JPI initialization
• The Problem: the HeapProxy recorder methods are defined as “native” and are bound by JPI only during the JVM_INIT event (because JNI services are not available before JVM_INIT)– This is problematic since for some system classes, CLASS_LOAD_HOOK
events are sent before JVM_INIT
– Inserting calls to native methods before they are bound cause the JVM to crash, even if these methods are never executed (just referencing these methods in the code is enough to crash the JVM)
• The Solution: HeapProxy has wrapper functions which are always called by instrumentation code that is inserted before JVM_INIT– Those functions check whether the JVM has already been initialized and call
the native ObjectAlloc functions only after the JVM has been initialized• i.e. object allocations before JVM_INIT after not communicated to the heap profiler
Eclipse TPTP
Object Alloc EventObject Alloc Event• Event Source
– Regular Objects: BCI of java.lang.Object.<init>– Arrays: BCI after callsites of newarray, anewarray, multianewarray– Internal VM Allocations: JVMTI_EVENT_VM_OBJECT_ALLOC
• Data Items– Object ID– Class ID– Thread id (of the allocating thread)– Object Size– Whether this object is an array
• Selectivity– By package/class
Eclipse TPTP
Object Free EventObject Free Event• Event Source
– JVMTI_EVENT_OBJECT_FREE for tagged objects
• Data Items– Object ID (easy - JVMTI)– All other information is optional
• Can also be looked-up using a data request
• Selectivity– By fully qualified class name– Defined at Object Allocation time for both Object Alloc and Free
events
Eclipse TPTP
Garbage Collection StartedGarbage Collection Started• Event Source
– JVMTI_EVENT_GARBAGE_COLLECTION_START
• Data Items– None
• Selectivity– None
• Notes– Generated only for “stop-the-world” collections. Other collections are
not reported.
Eclipse TPTP
Garbage Collection FinishedGarbage Collection Finished• Event Source
– JVMTI_EVENT_GARBAGE_COLLECTION_FINISH
• Data Items– None
• Selectivity– None
• Notes– See Garbage Collection Started
Eclipse TPTP
Heap Dump/Object ReferencesHeap Dump/Object References• TBD…
Eclipse TPTP
Open IssuesOpen Issues• Heap Dump data
– Need more info about the following XML fragments and their attributes:
• heapDumpDef• gcRoot• objectReference
• gcFinish element– Are the following attributes used by the viewers:
usedObjects, usedObjSpace, totalObjSpace
Eclipse TPTP
Thread ProfilerThread Profiler
Eclipse TPTP
Profiler RequirementsProfiler Requirements• Track Thread start and end events
• Track monitor events (critical sections, wait)
• Generate XML trace compatible with the JVMPI implementation
Eclipse TPTP
Martini RequirementsMartini Requirements• Generate the following events
– Thread Start– Thread End– Contended Monitor Enter– Contended Monitor Entered– Monitor Wait– Monitor Waited
• Support the following data requests– Get Object Monitor Usage information (from an object id)– Get Thread information (from a thread id)
Eclipse TPTP
Thread Start EventThread Start Event• Event Source
– JVMTI
• Data Items– Unique Thread ID– Thread Name– Parent Name– Group Name
• Selectivity– None
Eclipse TPTP
Thread End EventThread End Event• Event Source
– JVMTI
• Data Items– Thread ID
• Selectivity– None
Eclipse TPTP
Contended Monitor Enter EventContended Monitor Enter Event• Event Source
– JVMTI
• Data Items– Unique Monitor ID– The waiting thread id– The id of the thread owning the monitor
• Notes– Other monitor information can be obtained with a data request:
• For contended monitors: a list of threads waiting for the monitor• For “wait” monitors: a list of threads waiting to be notified
Eclipse TPTP
Contended Monitor Entered EventContended Monitor Entered Event• Event Source
– JVMTI
• Data Items– Monitor ID– The id of the thread that entered the monitor
• Selectivity– None
Eclipse TPTP
Monitor Wait EventMonitor Wait Event• Event Source
– JVMTI
• Data Items– Monitor ID– The id of the waiting thread– Wait timeout - the value passed to the obj.Wait() method
• Selectivity– None
Eclipse TPTP
Monitor Waited EventMonitor Waited Event• Event Source
– JVMTI
• Data Items– Monitor ID– The id of the waiting thread
• Selectivity– None
• Notes– The <monWaited> output element includes the “timeout” attribute that
specifies the number of milliseconds the thread had to wait for the monitor.
– This data item is not available in JVMTI so the profiler will have to calculate it manually
Eclipse TPTP
BackupBackup
Eclipse TPTP
HeapProxy Java ClassHeapProxy Java Classpublic class HeapProxy {
private static int m_bJVMInit = 0;
public static void JVMInit() { m_bJVMInit = 1; }
public static native void ObjectAlloc(java.lang.Object obj);
public static void EarlyObjectAlloc(java.lang.Object obj) {
if (m_bJVMInit != 0) ObjectAlloc(obj); }
public static native void ArrayAlloc(java.lang.Object arr);
public static void EarlyArrayAlloc(java.lang.Object arr) {
if (m_bJVMInit != 0) ArrayAlloc(obj);}
}
Eclipse TPTP
Instrumenting java.lang.Object ConstructorInstrumenting java.lang.Object Constructor
Before After
public Object()
{
}
public Object(){ HeapProxy.EarlyObjectAlloc(this);}
Best seen in Slide Show mode
Martini inserts a call to HeapProxy.EarlyObjectAlloc, because the insertion will always happen before the VM is initialized, and we cannot use native methods because they were not bound yet.
Eclipse TPTP
Instrumenting Array Allocation Callsites[case 1 – before JVM_INIT event received]
Instrumenting Array Allocation Callsites[case 1 – before JVM_INIT event received]
Before After
void someMethod()
{
…
…
int[] intArray =
new int[20];
…
…
}
Best seen in Slide Show mode
void someMethod()
{
…
…
int[] intArray =
new int[20];
HeapProxy.EarlyArrayAlloc(intArray);
…
…
}
Martini inserts a call to HeapProxy.EarlyArrayAlloc. Since the JVM has not been initialized yet, we cannot use native methods because they were not bound yet.
Eclipse TPTP
Instrumenting Array Allocation Callsites[case 2 – after JVM_INIT event received]Instrumenting Array Allocation Callsites
[case 2 – after JVM_INIT event received]
Before After
void someMethod()
{
…
…
int[] intArray =
new int[20];
…
…
}
Best seen in Slide Show mode
void someMethod()
{
…
…
int[] intArray =
new int[20];
HeapProxy.ArrayAlloc(intArray);
…
…
}
Martini inserts a call to HeapProxy.ArrayAlloc. Since the JVM has already initialized, we can safely use native methods because they were already bounded.
Eclipse TPTP
Heap Instrumentation OverviewHeap Instrumentation Overview
• Instrumenting the java.lang.Object constructor:– Add references to the HeapProxy class and the
HeapProxy.EarlyObjectAlloc function to the constant pool– Modify the method’s code attribute and inject code to call the
HeapProxy.EarlyObjectAlloc function.
• Instrumenting array allocation sites in a Java class:– Add references to the HeapProxy class and the HeapProxy.ArrayAlloc
or HeapProxy.EarlyObjectAlloc functions to the constant pool– Iterate over the class methods, and for each method that can be
instrumented (i.e. has a “code” attribute)• Search for any of the following array allocation instructions: newarray,
anewarray, multianewarray.
• If found, modify the method’s code attribute and inject code after each allocation site to call the HeapProxy.ArrayAlloc function.
Eclipse TPTP
java.lang.Object Constructor Instrumentation Detailsjava.lang.Object Constructor Instrumentation Details
return
.end
.start
Original method code
Legendpseudo-instructions
original instructions
new instructions
.start
inst1
sipush
Instrumented method code
.start
aload_0
invokestatic EarlyObjectAlloc()
.end
return
The ‘this’ pointer of the newly allocated object is stored in local variable 0. Load it to the operand stack so it can be passed to the EarlyObjectAlloc static function
Eclipse TPTP
Array Allocation Site Instrumentation DetailsArray Allocation Site Instrumentation Details
.end
.start
Original method code
Legendpseudo-instructions
original instructions
new instructions
.start
inst1
sipush
Instrumented method code.start
dup
invokestatic [Early]ArrayAlloc()
.end
inst
newarray
inst
inst
inst
inst
inst
newarray
inst
inst
After the ‘newarray’ instruction, a reference to the newly allocated array is on the operand stack. The reference is duplicated and sent to the ArrayAlloc or EarlyArrayAlloc static function