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<ClassItem*> *list = new vector<ClassItem*>();
            vector<ClassItem*>::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


