Martini Framework Design Overview
Martini framework is designed to cover different runtime environments Java VM and .NET CLR initially. Actually it mainly used for JVMTI on Java VM now. It also provides framework users an unified interface for different profilers based on MPI(Martini Profiling Interface).
There are five basic components in Martini internally. They are:
- MartiniOSA: This component is used to abstract common OS functions. Such as I/O and threads related functions are included.
- JPIBootLoader & LibraryLoader: They will load different components dynamically.
- JPI: Java Profiling function..
- JIE: Java instrumentation function.
- Instrumentation Adaptor: Instrumentation adaptors for call graph profiling (CGAdaptor), heap profiling (HeapAdaptor) and thread profiling (ThreadAdaptor).
Martini Profiling Events Design Keypoints
Unified Events Handling Interface
Observer pattern is used for this unified design. Martini implements a events notification system by separating events subjects and observers. Besides VM events, it also merges external control module events into framework.
Please refer the relation of main classes to here.
When a Java class is loaded by JVM, Class File Load event will be generated by JVM. In Martini framework, CJavaInstrumentorManager::InstrumentationEventHandler is used as this event handler. In this method, ModifyClass() and ModifyByteCodes() are called on InstrumentationAdaptor object m_pAdaptor.
For different profiling, three kinds of instrumentation adaptors are provided: CG Adaptor, Heap Adaptor and Thread Adaptor. Singleton, Factory and Proxy patterns are used in instrumentation design. The Singleton class CAdaptorFactory::CreateAdaptor(MPI::EEventGroup group) creates concrete Adaptor's proxy object (CCgAdaptorDelegate/CHeapAdaptorDelegate/CThreadAdaptorDelegate). When proxy object is initialized, it will create corresponding Adaptor object which will be used to implement instrumentation. Please refer the relation of classes in these instrumentation design to here.