Java Q&A by Andy Wilson Listing One /** JVMPI_Event -- Taken and modified from JVMPI.h */ typedef struct { jint event_type; /* event_type */ JNIEnv *env_id; /* env where this event occured */ union { struct { char *class_name; /* class name */ char *source_name; /* name of source file */ jint num_interfaces; /* number of interfaces implemented */ jint num_methods; /* number of methods in the class */ JVMPI_Method *methods; /* methods */ jint num_static_fields; /* number of static fields */ JVMPI_Field *statics; /* static fields */ jint num_instance_fields; /* number of instance fields */ JVMPI_Field *instances; /* instance fields */ jobjectID class_id; /* id of the class object */ } class_load; /* There are many more event data structures. */ } u; } JVMPI_Event; Listing Two public class Foo { int a; Object b; Object c; public static void main( String[] args ) { new Foo(); } } Listing Three // ProfilerHook.cpp // globals JVMPI_Interface* g_pProfiler; // Global profiler interface ref CRITICAL_SECTION g_criticalSection; // mutual exclusion mechanism CLASSMAP* g_pClasses; // stores the class list BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { if ( ul_reason_for_call == DLL_PROCESS_ATTACH ) { // initialize the critical section and the class map g_pClasses = new CLASSMAP(); InitializeCriticalSection ( &g_criticalSection ); } else if ( ul_reason_for_call == DLL_PROCESS_DETACH ) { DeleteCriticalSection( &g_criticalSection ); } return TRUE; } extern "C" JNIEXPORT jint JNICALL JVM_OnLoad( JavaVM *jvm, char *options, void *reserved) { // Get profiler interface and confirm you // have a compatible version of the VM int res = jvm->GetEnv((void**)&g_pProfiler, JVMPI_VERSION_1); if ( res < 0 ) return JNI_ERR; // error result // Reassign the profiler NotifyEvent function so we receive events g_pProfiler->NotifyEvent = HandleEvent; /** Register the events you want to receive. You need events for class * load, object allocation and shutdown. Class load gives you a mapping * between allocated object and class type. Shutdown lets you know when * the VM is closing and when to dump your information */ g_pProfiler->EnableEvent ( JVMPI_EVENT_CLASS_LOAD, NULL ); g_pProfiler->EnableEvent ( JVMPI_EVENT_OBJECT_ALLOC, NULL ); g_pProfiler->EnableEvent ( JVMPI_EVENT_JVM_SHUT_DOWN, NULL ); return JNI_OK; // success result } extern "C" void HandleEvent( JVMPI_Event *pEvent ) { int event = pEvent->event_type & 0xffff; // Enter a critical section since everything must be thread safe EnterCriticalSection( &g_criticalSection ); switch ( event ) { case JVMPI_EVENT_CLASS_LOAD: { /* Store the class so that we can colect memory information */ ClassItem* pItem = new ClassItem(pEvent); g_pClasses->insert( CLASSVALUE( pEvent->u.class_load.class_id, pItem ) ); } break; case JVMPI_EVENT_OBJECT_ALLOC: { /* Increment memory allocated to a class */ CLASSMAPITERATOR it = g_pClasses->find( pEvent->u.obj_alloc.class_id ); if ( it != g_pClasses->end() ) { ClassItem* pItem = (*it).second; pItem->count++; pItem->size += pEvent->u.obj_alloc.size; } } break; case JVMPI_EVENT_JVM_SHUT_DOWN: { /* Sort and dump the memory results */ long totalObjects = 0; long totalMemory = 0; cout << "\n\nShutdown Summary" << endl; cout << "Size\tCount\tName" << endl; CLASSMAPITERATOR it = g_pClasses->begin(); vector *list = new vector(); vector::iterator listIt; while ( it != g_pClasses->end() ) { ClassItem* pItem = (*it).second; list->push_back(pItem); totalObjects += pItem->count; totalMemory += pItem->size; it++; } sort( list->begin(), list->end(), ClassItemGreater() ); listIt = list->begin(); while ( listIt != list->end() ) { ClassItem* pItem = (*listIt); cout << pItem->size << "\t" << pItem->count << "\t" << pItem->szClassName << endl; listIt++; } cout << endl; cout << "Total Memory:\t" << totalMemory << endl; cout << "Total Objects:\t" << totalObjects << endl; g_pClasses->clear(); delete g_pClasses; } break; } // Leave the critical section LeaveCriticalSection( &g_criticalSection ); } Listing Four class HelloWorld { public static void main(String[] args ){ System.out.println( "Hello World!" ); } } 1