* Removed all Id tags.
[cacao.git] / src / native / jvmti / jvmti.c
index 85a69bfb385015e5f5d1710f8996a0f791234cc4..f4d613d389d500551cba4b2537f64341c5cf231a 100644 (file)
 
    Changes: Edwin Steiner
             Samuel Vinson
-
+            Christan Thalinger
    
-   $Id: jvmti.c 4945 2006-05-23 19:52:47Z motse $
-
 */
 
+
+#include "config.h"
+
 #include <assert.h>
+#include <string.h>
+#include <linux/unistd.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <ltdl.h>
+#include <unistd.h>
+#include <sched.h>
 
 #include "native/jni.h"
 #include "native/native.h"
 #include "native/jvmti/cacaodbg.h"
 #include "native/jvmti/jvmti.h"
+#include "vm/jit/stacktrace.h"
 #include "vm/global.h"
 #include "vm/loader.h"
 #include "vm/builtin.h"
 #include "vm/jit/asmpart.h"
 #include "vm/class.h"
 #include "vm/classcache.h"
-#include "mm/boehm.h"
+#include "mm/gc-common.h"
 #include "toolbox/logging.h"
 #include "vm/options.h"
 #include "vm/stringlocal.h"
 #include "native/include/java_lang_VMSystem.h"
 #include "native/include/java_lang_VMClass.h"
 #include "vm/suck.h"
-#include  "boehm-gc/include/gc.h"
-
-#include <string.h>
-#include <linux/unistd.h>
-#include <sys/time.h>
-#include "toolbox/logging.h"
-#include <stdlib.h>
-#include <sys/types.h>
-#include <ltdl.h>
-#include <unistd.h>
-#include <sched.h>
+#include "boehm-gc/include/gc.h"
 
 #if defined(ENABLE_THREADS)
 #include "threads/native/threads.h"
@@ -125,10 +125,11 @@ static lt_ptr unload;
 #define CHECK_PHASE_START  if (!(false 
 #define CHECK_PHASE(chkphase) || (phase == chkphase)
 #define CHECK_PHASE_END  )) return JVMTI_ERROR_WRONG_PHASE
-#define CHECK_CAPABILITY(env,CAP) if(((environment*)env)->capabilities.CAP == 0) \
+#define CHECK_CAPABILITY(env,CAP) if(((environment*)                            \
+                                                                                env)->capabilities.CAP == 0)           \
                                      return JVMTI_ERROR_MUST_POSSESS_CAPABILITY;
-#define CHECK_THREAD_IS_ALIVE(t) if(check_thread_is_alive(t)== \
-                                  JVMTI_ERROR_THREAD_NOT_ALIVE) \
+#define CHECK_THREAD_IS_ALIVE(t) if(check_thread_is_alive(t) ==                 \
+                                  JVMTI_ERROR_THREAD_NOT_ALIVE)                 \
                                        return JVMTI_ERROR_THREAD_NOT_ALIVE;
 
 
@@ -140,13 +141,13 @@ static lt_ptr unload;
 
 *******************************************************************************/
 static jvmtiError check_thread_is_alive(jthread t) {
-       if(t==NULL) return JVMTI_ERROR_THREAD_NOT_ALIVE;
-       if(((java_lang_Thread*) t)->vmThread==NULL) 
+       if(t == NULL) return JVMTI_ERROR_THREAD_NOT_ALIVE;
+       if(((java_lang_Thread*) t)->vmThread == NULL) 
                return JVMTI_ERROR_THREAD_NOT_ALIVE;
        return JVMTI_ERROR_NONE;
 }
 
-/* execcallback ***************************************************************
+/* execute_callback ************************************************************
 
    executes the registerd callbacks for the given jvmti event with parameter
    in the data structure.
@@ -181,6 +182,13 @@ static void execute_callback(jvmtiEvent e, functionptr ec,
                                                                                   data->class_data,
                                                                                   data->new_class_data_len,
                                                                                   data->new_class_data);
+
+               /* if class data has been modified use it as class data for other agents 
+                  waiting for the same event */
+               if (data->new_class_data != NULL) {
+                       data->jint1 = *(data->new_class_data_len);
+                       data->class_data = *(data->new_class_data); 
+               }
                break;
 
 
@@ -370,22 +378,25 @@ static void dofireEvent(jvmtiEvent e, genericEventData* data) {
        functionptr ec;
 
        env = envs;
-       while (env!=NULL) {
+       while (env != NULL) {
                if (env->events[e-JVMTI_EVENT_START_ENUM].mode == JVMTI_DISABLE) {
                        evm = env->events[e-JVMTI_EVENT_START_ENUM].next;
             /* test if the event is enable for some threads */
-                       while (evm!=NULL) { 
+                       while (evm != NULL) { 
                                if (evm->mode == JVMTI_ENABLE) {
-                                       data->jvmti_env=&env->env;
-                                       ec = ((functionptr*)(&env->callbacks))[e-JVMTI_EVENT_START_ENUM];
-                                       execute_callback(e, ec, data);
+                                       ec = ((functionptr*)
+                                                 (&env->callbacks))[e-JVMTI_EVENT_START_ENUM];
+                                       if (ec != NULL) {
+                                               data->jvmti_env=&env->env;
+                                               execute_callback(e, ec, data);
+                                       }
                                }
                                evm=evm->next;
                        }
                } else { /* event enabled globally */
                        data->jvmti_env=&env->env;
                        ec = ((functionptr*)(&env->callbacks))[e-JVMTI_EVENT_START_ENUM];
-                       execute_callback(e, ec, data);
+                       if (ec != NULL) execute_callback(e, ec, data);
                }
                
                env=env->next;
@@ -403,10 +414,11 @@ void jvmti_fireEvent(genericEventData* d) {
        jthread thread;
     /* XXX todo : respect event order JVMTI-Spec:Multiple Co-located Events */
 
-       if (d->ev != JVMTI_EVENT_VM_START)
-               thread = jvmti_get_current_thread();
-       else
+       if (d->ev == JVMTI_EVENT_VM_START)
                thread = NULL;
+       else
+               thread = jvmti_get_current_thread();
+
 
        d->thread = thread;
        dofireEvent(d->ev,d);
@@ -437,7 +449,6 @@ SetEventNotificationMode (jvmtiEnv * env, jvmtiEventMode mode,
                CHECK_THREAD_IS_ALIVE(event_thread);
        }
        
-
        cacao_env = (environment*) env;    
        if ((mode != JVMTI_ENABLE) && (mode != JVMTI_DISABLE))
                return JVMTI_ERROR_ILLEGAL_ARGUMENT;
@@ -491,13 +502,6 @@ SetEventNotificationMode (jvmtiEnv * env, jvmtiEventMode mode,
     case JVMTI_EVENT_VM_OBJECT_ALLOC:
                CHECK_CAPABILITY(env,can_generate_vm_object_alloc_events)
                break;
-    case JVMTI_EVENT_THREAD_START:
-               jvmti_set_system_breakpoint(THREADSTARTBRK, mode);
-               break;
-    case JVMTI_EVENT_THREAD_END:
-               jvmti_set_system_breakpoint(THREADENDBRK, mode);
-               break;
-
        default:
                /* all other events are required */
                if ((event_type < JVMTI_EVENT_START_ENUM) ||
@@ -506,6 +510,7 @@ SetEventNotificationMode (jvmtiEnv * env, jvmtiEventMode mode,
                break;
        }
 
+
        if (event_thread != NULL) {
                /* thread level control */
                if ((JVMTI_EVENT_VM_INIT == mode) ||
@@ -584,9 +589,15 @@ SuspendThread (jvmtiEnv * env, jthread thread)
        CHECK_PHASE_END;
     CHECK_CAPABILITY(env,can_suspend);
     
-       log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!");
-       return JVMTI_ERROR_NOT_AVAILABLE;
+       if(thread == NULL) return JVMTI_ERROR_INVALID_THREAD;
+       if (!builtin_instanceof(thread,class_java_lang_Thread))
+               return JVMTI_ERROR_INVALID_THREAD;
+       CHECK_THREAD_IS_ALIVE(thread);
 
+    /* threads_suspend_thread will implement suspend
+          threads_suspend_thread (
+          (threadobject*)((java_lang_Thread*) thread)->vmThread))*/
+       
     return JVMTI_ERROR_NONE;
 }
 
@@ -604,8 +615,14 @@ ResumeThread (jvmtiEnv * env, jthread thread)
     CHECK_PHASE_END;
     CHECK_CAPABILITY(env,can_suspend);
 
-       log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!");
-       return JVMTI_ERROR_NOT_AVAILABLE;
+       if(thread == NULL) return JVMTI_ERROR_INVALID_THREAD;
+       if (!builtin_instanceof(thread,class_java_lang_Thread))
+               return JVMTI_ERROR_INVALID_THREAD;
+       CHECK_THREAD_IS_ALIVE(thread);
+
+    /* threads_resume_thread will implement resume
+          threads_resume_thread (
+          (threadobject*)((java_lang_Thread*) thread)->vmThread))*/
 
     return JVMTI_ERROR_NONE;
 }
@@ -645,16 +662,19 @@ InterruptThread (jvmtiEnv * env, jthread thread)
     CHECK_PHASE_END;
     CHECK_CAPABILITY(env,can_signal_thread)
 
-       log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!");
-
-       return JVMTI_ERROR_NOT_AVAILABLE;
-
+#if defined(ENABLE_THREADS)
        if(!builtin_instanceof(thread,class_java_lang_Thread))
                return JVMTI_ERROR_INVALID_THREAD;
 
-       CHECK_THREAD_IS_ALIVE(thread);        
+       CHECK_THREAD_IS_ALIVE(thread);
+
+       threads_thread_interrupt(((java_lang_Thread *) thread)->vmThread);
+
 
     return JVMTI_ERROR_NONE;
+#else
+       return JVMTI_ERROR_NOT_AVAILABLE;
+#endif
 }
 
 /* GetThreadInfo ***************************************************************
@@ -667,23 +687,29 @@ InterruptThread (jvmtiEnv * env, jthread thread)
 static jvmtiError
 GetThreadInfo (jvmtiEnv * env, jthread t, jvmtiThreadInfo * info_ptr)
 {
+       utf *name;
        java_lang_Thread* th = (java_lang_Thread*)t;
 
+
     CHECK_PHASE_START
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
+
        info_ptr->priority=(jint)th->priority;
        info_ptr->is_daemon=(jboolean)th->daemon;
        info_ptr->thread_group=(jthreadGroup)th->group;
        info_ptr->context_class_loader=(jobject)th->contextClassLoader;
-       info_ptr->name= javastring_tochar((java_objectheader *)th->name);
+
+       name = javastring_toutf(th->name,false);
+       info_ptr->name=(char*)heap_allocate(sizeof(char)*(utf_bytes(name)+1),true,NULL);
+       utf_sprint_convert_to_latin1(info_ptr->name, name);
 
     return JVMTI_ERROR_NONE;
 }
 
 /* GetOwnedMonitorInfo *********************************************************
 
-   Get information about the monitors owned by the specified thread
+   Gets all  monitors owned by the specified thread
 
 *******************************************************************************/
 
@@ -695,21 +721,25 @@ GetOwnedMonitorInfo (jvmtiEnv * env, jthread thread,
        int i,j,size=20;
        java_objectheader **om;
        lock_record_pool_t* lrp;
-
-       log_text("GetOwnedMonitorInfo called");
+       threadobject* t;
 
        CHECK_PHASE_START
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
     CHECK_CAPABILITY(env,can_get_owned_monitor_info);
 
-       if ((owned_monitors_ptr==NULL)||(owned_monitor_count_ptr==NULL)) 
+       if ((owned_monitors_ptr == NULL)||(owned_monitor_count_ptr == NULL)) 
                return JVMTI_ERROR_NULL_POINTER;
 
-       if(!builtin_instanceof(thread,class_java_lang_Thread))
-               return JVMTI_ERROR_INVALID_THREAD;
-
-       CHECK_THREAD_IS_ALIVE(thread);
+       if (thread == NULL) {
+               t = jvmti_get_current_thread();
+       } else {
+               if(!builtin_instanceof(thread,class_java_lang_Thread))
+                       return JVMTI_ERROR_INVALID_THREAD;
+               
+               CHECK_THREAD_IS_ALIVE(thread);
+               t = (threadobject*) thread;
+       }
 
 #if defined(ENABLE_THREADS)
 
@@ -718,26 +748,30 @@ GetOwnedMonitorInfo (jvmtiEnv * env, jthread thread,
        pthread_mutex_lock(&lock_global_pool_lock);
        lrp=lock_global_pool;
 
+       /* iterate over all lock record pools */
        while (lrp != NULL) {
+               /* iterate over every lock record in a pool */
                for (j=0; j<lrp->header.size; j++) {
-/*                     if((lrp->lr[j].owner==(threadobject*)thread)&&
-                          (!lrp->lr[j].waiting)) {
-                               if (i>=size) {
-                                       MREALLOC(om,java_objectheader*,size,size*2);
-                                       size=size*2;
+                       /* if the lock record is owned by the given thread add it to 
+                          the result array */
+                       if(lrp->lr[j].owner == t) {
+                               if (i >= size) {
+                                       MREALLOC(om, java_objectheader*, size, size * 2);
+                                       size = size * 2;
                                }
-                               om[i]=lrp->lr[j].o;
+                               om[i] = lrp->lr[j].obj;
                                i++;
-                               }*/
+                               }
                }
                lrp=lrp->header.next;
        }
 
        pthread_mutex_unlock(&lock_global_pool_lock);
 
-       *owned_monitors_ptr     = heap_allocate(sizeof(java_objectheader*)*i,true,NULL);
-       memcpy(*owned_monitors_ptr,om,i*sizeof(java_objectheader*));
-       MFREE(om,java_objectheader*,size);
+       *owned_monitors_ptr     = 
+               heap_allocate(sizeof(java_objectheader*) * i, true, NULL);
+       memcpy(*owned_monitors_ptr, om, i * sizeof(java_objectheader*));
+       MFREE(om, java_objectheader*, size);
 
        *owned_monitor_count_ptr = i;
 
@@ -758,21 +792,26 @@ GetCurrentContendedMonitor (jvmtiEnv * env, jthread thread,
 {
        int j;
        lock_record_pool_t* lrp;
-       java_objectheader* monitor;
+       threadobject* t;
+       lock_waiter_t* waiter;
 
        CHECK_PHASE_START
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
        CHECK_CAPABILITY(env, can_get_current_contended_monitor)
         
-       if (monitor_ptr==NULL) return JVMTI_ERROR_NULL_POINTER;
+       if (monitor_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;
        *monitor_ptr=NULL;
 
-       if(!builtin_instanceof(thread,class_java_lang_Thread))
-               return JVMTI_ERROR_INVALID_THREAD;
-
-       CHECK_THREAD_IS_ALIVE(thread);
-
+       if (thread == NULL) {
+               t = jvmti_get_current_thread();
+       } else {
+               if(!builtin_instanceof(thread,class_java_lang_Thread))
+                       return JVMTI_ERROR_INVALID_THREAD;
+               
+               CHECK_THREAD_IS_ALIVE(thread);
+               t = (threadobject*) thread;
+       }
 
 #if defined(ENABLE_THREADS)
 
@@ -780,22 +819,25 @@ GetCurrentContendedMonitor (jvmtiEnv * env, jthread thread,
 
        lrp=lock_global_pool;
 
-       while ((lrp != NULL)&&(monitor==NULL)) {
+       /* iterate over all lock record pools */
+       while ((lrp != NULL) && (*monitor_ptr == NULL)) {
+               /* iterate over every lock record in a pool */
                for (j=0; j<lrp->header.size; j++) {
-/*                     if((lrp->lr[j].owner==(threadobject*)thread)&&(lrp->lr[j].waiting)) {
-                               monitor=lrp->lr[j].o;
-                               break;
-                               }*/
+                       /* iterate over every thread that is wait on this lock record */
+                       waiter = lrp->lr[j].waiters;
+                       while (waiter != NULL) 
+                               /* if the waiting thread equals to the given thread we are 
+                                  done. Stop iterateting. */
+                               if(waiter->waiter == t) {
+                                       *monitor_ptr=lrp->lr[j].obj;
+                                       break;
+                               }
                }
                lrp=lrp->header.next;
        }
 
        pthread_mutex_unlock(&lock_global_pool_lock);
 
-       if (monitor!=NULL) {
-               *monitor_ptr = heap_allocate(sizeof(java_objectheader*),true,NULL);
-               *monitor_ptr = (jobject)monitor;
-       }
 
 #endif
     return JVMTI_ERROR_NONE;
@@ -840,7 +882,7 @@ RunAgentThread (jvmtiEnv * env, jthread thread, jvmtiStartFunction proc,
                (priority > JVMTI_THREAD_MAX_PRIORITY)) 
                return JVMTI_ERROR_INVALID_PRIORITY;
 
-       /* XXX:  Threads started with with this function should not be visible to 
+       /* XXX:  Threads started with this function should not be visible to 
           Java programming language queries but are included in JVM TI queries */
 
        rap.sf = proc;
@@ -887,8 +929,6 @@ GetTopThreadGroups (jvmtiEnv * env, jint * group_count_ptr,
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
 
-       log_text("GetTopThreadGroups called");
-
     if ((groups_ptr == NULL) || (group_count_ptr == NULL)) 
         return JVMTI_ERROR_NULL_POINTER;
 
@@ -1001,14 +1041,16 @@ GetThreadGroupChildren (jvmtiEnv * env, jthreadGroup group,
 
        *thread_count_ptr = (jint)tgp->threads->elementCount;
 
-       *threads_ptr = heap_allocate(sizeof(jthread*)*(*thread_count_ptr),true,NULL);
+       *threads_ptr = 
+               heap_allocate(sizeof(jthread)*(*thread_count_ptr),true,NULL);
 
        memcpy(*threads_ptr, &tgp->threads->elementData, 
-                  (*thread_count_ptr)*sizeof(jthread*));
+                  (*thread_count_ptr)*sizeof(java_objectarray*));
 
        *group_count_ptr = (jint) tgp->groups->elementCount;
 
-       *groups_ptr     = heap_allocate(sizeof(jthreadGroup*)*(*group_count_ptr),true,NULL);    
+       *groups_ptr     = 
+               heap_allocate(sizeof(jthreadGroup)*(*group_count_ptr),true,NULL);       
 
        memcpy(*groups_ptr, &tgp->threads->elementData,
                   (*group_count_ptr)*sizeof(jthreadGroup*));
@@ -1020,18 +1062,26 @@ GetThreadGroupChildren (jvmtiEnv * env, jthreadGroup group,
 /* getcacaostacktrace *********************************************************
 
    Helper function that retrives stack trace for specified thread. 
-   Has to take care of suspend/resume issuses
-
+   
 *******************************************************************************/
+
 static jvmtiError getcacaostacktrace(stacktracebuffer** trace, jthread thread) {
        threadobject *t;
-
-       log_text("getcacaostacktrace");
-
-       t = (threadobject*)((java_lang_Thread*)thread)->vmThread;
-
-/*      XXX todo
- *trace = stacktrace_create(t); */
+       bool resume;
+       
+       if (thread == NULL) {
+               t = jvmti_get_current_thread();
+               *trace = stacktrace_create(t);
+       } else {
+               t = (threadobject*)((java_lang_Thread*)thread)->vmThread;
+/*             if (t != jvmti_get_current_thread())
+                       resume = threads_suspend_thread_if_running(thread);
+    
+               *trace = stacktrace_create(thread );
+               
+               if (resume)
+               threads_resume_thread ( thread );*/
+       }
 
     return JVMTI_ERROR_NONE;
 }
@@ -1040,7 +1090,8 @@ static jvmtiError getcacaostacktrace(stacktracebuffer** trace, jthread thread) {
 /* GetFrameCount **************************************************************
 
 
-   Get the number of frames in the specified thread's stack.
+   Get the number of frames in the specified thread's stack. Calling function
+   has to take care of suspending/resuming thread.
 
 *******************************************************************************/
 
@@ -1054,18 +1105,24 @@ GetFrameCount (jvmtiEnv * env, jthread thread, jint * count_ptr)
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
     
-       if(!builtin_instanceof(thread,class_java_lang_Thread))
-               return JVMTI_ERROR_INVALID_THREAD;
+       if (thread != NULL){
+               if(!builtin_instanceof(thread,class_java_lang_Thread))
+                       return JVMTI_ERROR_INVALID_THREAD;
 
-       CHECK_THREAD_IS_ALIVE(thread);
+               CHECK_THREAD_IS_ALIVE(thread);
+       }
        
        if(count_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;
 
        er = getcacaostacktrace(&trace, thread);
-       if (er==JVMTI_ERROR_NONE) return er;
+       if (er == JVMTI_ERROR_NONE) {
+               heap_free(trace);
+               return er;
+       }
 
        *count_ptr = trace->used;
 
+       heap_free(trace);
     return JVMTI_ERROR_NONE;
 }
 
@@ -1093,7 +1150,7 @@ GetThreadState (jvmtiEnv * env, jthread thread, jint * thread_state_ptr)
 
        *thread_state_ptr = 0;
 #if defined(ENABLE_THREADS)
-       if((th->vmThread==NULL)&&(th->group==NULL)) { /* alive ? */
+       if((th->vmThread == NULL)&&(th->group == NULL)) { /* alive ? */
                /* not alive */
                if (((threadobject*)th->vmThread)->tid == 0)
                        *thread_state_ptr = JVMTI_THREAD_STATE_TERMINATED;
@@ -1101,7 +1158,7 @@ GetThreadState (jvmtiEnv * env, jthread thread, jint * thread_state_ptr)
                /* alive */
                *thread_state_ptr = JVMTI_THREAD_STATE_ALIVE;
                if (t->interrupted) *thread_state_ptr |= JVMTI_THREAD_STATE_INTERRUPTED;
-               /* todo */
+               /* XXX todo -  info not available */
                if (false) *thread_state_ptr |= JVMTI_THREAD_STATE_SUSPENDED;
                if (false) *thread_state_ptr |= JVMTI_THREAD_STATE_IN_NATIVE;
                if (false) *thread_state_ptr |= JVMTI_THREAD_STATE_RUNNABLE;
@@ -1133,22 +1190,28 @@ GetFrameLocation (jvmtiEnv * env, jthread thread, jint depth,
 {
        stackframeinfo   *sfi;
        int i;
+       threadobject* th;
                
        CHECK_PHASE_START
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
         
-       if(!builtin_instanceof(thread,class_java_lang_Thread))
-               return JVMTI_ERROR_INVALID_THREAD;
-
-       CHECK_THREAD_IS_ALIVE(thread);
+       if (thread == NULL) {
+               th = jvmti_get_current_thread();
+       } else {
+               if(!builtin_instanceof(thread,class_java_lang_Thread))
+                       return JVMTI_ERROR_INVALID_THREAD;
+               
+               CHECK_THREAD_IS_ALIVE(thread);
+               th = (threadobject*) ((java_lang_Thread*)thread)->vmThread;
+       }
 
        if (depth < 0) return JVMTI_ERROR_ILLEGAL_ARGUMENT;
 
        if ((method_ptr == NULL)&&(location_ptr == NULL)) 
                return JVMTI_ERROR_NULL_POINTER;
        
-       sfi = ((threadobject*)thread)->_stackframeinfo;
+       sfi = th->_stackframeinfo;
        
        i = 0;
        while ((sfi != NULL) && (i<depth)) {
@@ -1431,9 +1494,9 @@ DestroyRawMonitor (jvmtiEnv * env, jrawMonitorID monitor)
        if (!lock_is_held_by_current_thread((java_objectheader*)monitor->name))
                return JVMTI_ERROR_NOT_MONITOR_OWNER;
        
-       lock_monitor_exit((threadobject*)THREADOBJECT, (java_objectheader*)monitor->name);
+       lock_monitor_exit((java_objectheader *) monitor->name);
 
-       /* GC will clean monitor up */
+       heap_free(monitor);
 #else
        log_text ("DestroyRawMonitor not supported");
 #endif
@@ -1455,7 +1518,7 @@ RawMonitorEnter (jvmtiEnv * env, jrawMonitorID monitor)
                return JVMTI_ERROR_INVALID_MONITOR;
 
 #if defined(ENABLE_THREADS)
-       builtin_monitorenter((java_objectheader*)monitor->name);        
+       lock_monitor_enter((java_objectheader *) monitor->name);
 #else
        log_text ("RawMonitorEnter not supported");
 #endif
@@ -1481,7 +1544,7 @@ RawMonitorExit (jvmtiEnv * env, jrawMonitorID monitor)
        if (!lock_is_held_by_current_thread((java_objectheader*)monitor->name))
                return JVMTI_ERROR_NOT_MONITOR_OWNER;
 
-       builtin_monitorexit((java_objectheader*)monitor->name);
+       lock_monitor_exit((java_objectheader *) monitor->name);
 #else
        log_text ("RawMonitorExit not supported");
 #endif
@@ -1739,16 +1802,21 @@ GetClassSignature (jvmtiEnv * env, jclass klass, char **signature_ptr,
     CHECK_PHASE(JVMTI_PHASE_START)
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
-       
-    if ((generic_ptr== NULL)||(signature_ptr == NULL)) 
-        return JVMTI_ERROR_NULL_POINTER;
+    
+       if (klass == NULL) return JVMTI_ERROR_INVALID_CLASS;
+       if (!builtin_instanceof(klass,class_java_lang_Class))
+               return JVMTI_ERROR_INVALID_CLASS;
 
-    *signature_ptr = (char*)
-               heap_allocate(sizeof(char) * 
-                                         ((classinfo*)klass)->name->blength,true,NULL);
+       if (signature_ptr != NULL) {
+               *signature_ptr = (char*)
+                       heap_allocate(sizeof(char) * 
+                                                 utf_bytes(((classinfo*)klass)->name)+1,true,NULL);
+               
+               utf_sprint_convert_to_latin1(*signature_ptr,((classinfo*)klass)->name);
+       }
 
-       utf_sprint_convert_to_latin1(*signature_ptr, ((classinfo*)klass)->name);
-    *generic_ptr = NULL;
+       if (generic_ptr!= NULL)
+               *generic_ptr = NULL;
 
     return JVMTI_ERROR_NONE;
 }
@@ -1778,13 +1846,13 @@ GetClassStatus (jvmtiEnv * env, jclass klass, jint * status_ptr)
        *status_ptr = 0;        
 
 /*     if (c) *status_ptr = *status_ptr | JVMTI_CLASS_STATUS_VERIFIED; ? */
-       if (c->state&=CLASS_LINKED) 
+       if (c->state & CLASS_LINKED) 
                *status_ptr = *status_ptr | JVMTI_CLASS_STATUS_PREPARED;
 
-       if (c->state&=CLASS_INITIALIZED) 
+       if (c->state & CLASS_INITIALIZED) 
                *status_ptr = *status_ptr | JVMTI_CLASS_STATUS_INITIALIZED;
 
-       if (c->state&=CLASS_ERROR) 
+       if (c->state & CLASS_ERROR) 
                *status_ptr = *status_ptr | JVMTI_CLASS_STATUS_ERROR;
 
        if (c->vftbl->arraydesc != NULL) 
@@ -1817,7 +1885,7 @@ GetSourceFileName (jvmtiEnv * env, jclass klass, char **source_name_ptr)
     if ((klass == NULL)||(source_name_ptr == NULL)) 
         return JVMTI_ERROR_NULL_POINTER;
     
-    size = (((classinfo*)klass)->sourcefile->blength)+1;
+    size = utf_bytes(((classinfo*)klass)->sourcefile)+1;
 
     *source_name_ptr = (char*) heap_allocate(sizeof(char)* size,true,NULL);
     
@@ -2093,19 +2161,29 @@ GetFieldName (jvmtiEnv * env, jclass klass, jfieldID field,
     CHECK_PHASE(JVMTI_PHASE_START)
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
-        
-    if ((field == NULL)||(name_ptr == NULL)||(signature_ptr == NULL)) 
-        return JVMTI_ERROR_NULL_POINTER;
+
+       if (klass == NULL) 
+               return JVMTI_ERROR_INVALID_CLASS;
+       else 
+               if (!builtin_instanceof(klass,class_java_lang_Class))
+                       return JVMTI_ERROR_INVALID_CLASS;
+    if (field == NULL) return JVMTI_ERROR_INVALID_FIELDID;
     
-    size = (((fieldinfo*)field)->name->blength);
-    *name_ptr = (char*) heap_allocate(sizeof(char)* size,true,NULL);    
-    memcpy(*name_ptr,((fieldinfo*)field)->name->text, size);
+    if (name_ptr != NULL) {
+               size = utf_bytes(((fieldinfo*)field)->name)+1;
+               *name_ptr = (char*) heap_allocate(sizeof(char)* size,true,NULL);
+               utf_sprint_convert_to_latin1(*name_ptr, ((fieldinfo*)field)->name);
+       }
 
-    size = (((fieldinfo*)field)->descriptor->blength);
-    *signature_ptr = (char*) heap_allocate(sizeof(char)* size,true,NULL);    
-    memcpy(*signature_ptr,((fieldinfo*)field)->descriptor->text, size);
+       if (signature_ptr != NULL) {
+               size = utf_bytes(((fieldinfo*)field)->descriptor)+1;
+               *signature_ptr = (char*) heap_allocate(sizeof(char)* size,true,NULL); 
+               utf_sprint_convert_to_latin1(*signature_ptr, 
+                                                                        ((fieldinfo*)field)->descriptor);
+       }
 
-    *generic_ptr = NULL;
+       if (generic_ptr != NULL) 
+               *generic_ptr = NULL;
 
     return JVMTI_ERROR_NONE;
 }
@@ -2127,7 +2205,17 @@ GetFieldDeclaringClass (jvmtiEnv * env, jclass klass, jfieldID field,
     CHECK_PHASE(JVMTI_PHASE_START)
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
-        
+
+       if (klass == NULL) 
+               return JVMTI_ERROR_INVALID_CLASS;
+       else 
+               if (!builtin_instanceof(klass,class_java_lang_Class))
+                       return JVMTI_ERROR_INVALID_CLASS;
+
+    if (field == NULL) return JVMTI_ERROR_INVALID_FIELDID;     
+
+    if (declaring_class_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;
+
        *declaring_class_ptr = (jclass) ((fieldinfo*)field)->class;
  
     return JVMTI_ERROR_NONE;
@@ -2148,14 +2236,17 @@ GetFieldModifiers (jvmtiEnv * env, jclass klass, jfieldID field,
     CHECK_PHASE(JVMTI_PHASE_START)
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
-        
-       if (!builtin_instanceof((java_objectheader*)klass, class_java_lang_Class))
-               return JVMTI_ERROR_INVALID_OBJECT;
+
+       if (klass == NULL) 
+               return JVMTI_ERROR_INVALID_CLASS;
+       else 
+               if (!builtin_instanceof(klass,class_java_lang_Class))
+                       return JVMTI_ERROR_INVALID_CLASS;
+
+    if (field == NULL) return JVMTI_ERROR_INVALID_FIELDID;
 
        if (modifiers_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;
  
-       /* todo: JVMTI_ERROR_INVALID_FIELDID; */
-       
        *modifiers_ptr = ((fieldinfo*)field)->flags;
        
     return JVMTI_ERROR_NONE;
@@ -2201,19 +2292,25 @@ GetMethodName (jvmtiEnv * env, jmethodID method, char **name_ptr,
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
 
-    if ((method == NULL) || (name_ptr == NULL) || (signature_ptr == NULL)
-        || (generic_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER;
 
-    *name_ptr = (char*)
-               heap_allocate(sizeof(char) * (m->name->blength),true,NULL);
-       utf_sprint_convert_to_latin1(*name_ptr, m->name);
+       if (method == NULL) return JVMTI_ERROR_INVALID_METHODID;
 
-    *signature_ptr = (char*)
-               heap_allocate(sizeof(char) * (m->descriptor->blength),true,NULL);
-       utf_sprint_convert_to_latin1(*signature_ptr, m->descriptor);
+       if (name_ptr != NULL) {
+               *name_ptr = (char*)
+                       heap_allocate(sizeof(char) * (utf_bytes(m->name)+1),true,NULL);
+               utf_sprint_convert_to_latin1(*name_ptr, m->name);
+       }
+       
+       if (signature_ptr != NULL) {
+               *signature_ptr = (char*)
+                       heap_allocate(sizeof(char)*(utf_bytes(m->descriptor)+1),true,NULL);
+               utf_sprint_convert_to_latin1(*signature_ptr, m->descriptor);
+       }
 
-    /* there is no generic signature attribute */
-    *generic_ptr = NULL;
+       if (generic_ptr != NULL) {
+        /* there is no generic signature attribute */
+               *generic_ptr = NULL;
+       }
 
     return JVMTI_ERROR_NONE;
 }
@@ -2287,7 +2384,7 @@ GetMaxLocals (jvmtiEnv * env, jmethodID method, jint * max_ptr)
     
     if (((methodinfo*)method)->flags & ACC_NATIVE)  
         return JVMTI_ERROR_NATIVE_METHOD;
-   
     *max_ptr = (jint) ((methodinfo*)method)->maxlocals;
 
     return JVMTI_ERROR_NONE;
@@ -2315,13 +2412,13 @@ GetArgumentsSize (jvmtiEnv * env, jmethodID method, jint * size_ptr)
     if (((methodinfo*)method)->flags & ACC_NATIVE)  
         return JVMTI_ERROR_NATIVE_METHOD;
 
-/* todo    *size_ptr = (jint)((methodinfo*)method)->paramcount;*/
+    *size_ptr = (jint)((methodinfo*)method)->parseddesc->paramslots;
     return JVMTI_ERROR_NONE;
 }
 
 
 
-/* GetLineNumberTable ***********************************************************
+/* GetLineNumberTable **********************************************************
 
    Return table of source line number entries for a given method
 
@@ -2341,8 +2438,10 @@ GetLineNumberTable (jvmtiEnv * env, jmethodID method,
    
     if ((method == NULL) || (entry_count_ptr == NULL) || (table_ptr == NULL)) 
         return JVMTI_ERROR_NULL_POINTER;    
+
     if (((methodinfo*)method)->flags & ACC_NATIVE)  
         return JVMTI_ERROR_NATIVE_METHOD;
+
     if (((methodinfo*)method)->linenumbers == NULL) 
         return JVMTI_ERROR_ABSENT_INFORMATION;
 
@@ -2352,9 +2451,9 @@ GetLineNumberTable (jvmtiEnv * env, jmethodID method,
 
 
     for (i=0; i < *entry_count_ptr; i++) {
-        (*table_ptr[i]).start_location = 
+        (*table_ptr)[i].start_location = 
             (jlocation) ((methodinfo*)method)->linenumbers[i].start_pc;
-        (*table_ptr[i]).line_number = 
+        (*table_ptr)[i].line_number = 
             (jint) ((methodinfo*)method)->linenumbers[i].line_number;
     }
     
@@ -2382,8 +2481,13 @@ GetMethodLocation (jvmtiEnv * env, jmethodID method,
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
 
-    if ((method == NULL) || (start_location_ptr == NULL) || 
-        (end_location_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER;
+       if (method == NULL)     return JVMTI_ERROR_INVALID_METHODID;
+
+       if (((methodinfo*)method)->flags & ACC_NATIVE) 
+               return JVMTI_ERROR_NATIVE_METHOD;
+
+    if ((start_location_ptr == NULL) || (end_location_ptr == NULL)) 
+       return JVMTI_ERROR_NULL_POINTER;
     
        /* XXX we return the location of the most recent code. Don't know
         * if there is a way to teach jvmti that a method can have more
@@ -2392,11 +2496,16 @@ GetMethodLocation (jvmtiEnv * env, jmethodID method,
        /* XXX Don't know if that's the right way to deal with not-yet-
         * compiled methods. -Edwin */
 
-       if (!m->code)
-               return JVMTI_ERROR_NULL_POINTER;
-       
+    fprintf(stderr,"GetMethodLocation *** XXX todo \n");
+
+
+       /* -1 states location information is not available */
+    *start_location_ptr = (jlocation)-1;
+    *end_location_ptr = (jlocation)-1;
+
+/*     
     *start_location_ptr = (jlocation)m->code->mcode;
-    *end_location_ptr = (jlocation)(m->code->mcode)+m->code->mcodelength;
+    *end_location_ptr = (jlocation)(m->code->mcode)+m->code->mcodelength;*/
     return JVMTI_ERROR_NONE;
 }
 
@@ -2511,50 +2620,17 @@ IsMethodSynthetic (jvmtiEnv * env, jmethodID method,
 static jvmtiError
 GetLoadedClasses (jvmtiEnv * env, jint * class_count_ptr, jclass ** classes_ptr)
 {
-       int i,j=0;
-       classcache_name_entry *nameentry;
-       classcache_class_entry *classentry;
-
     CHECK_PHASE_START
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
 
-    if (class_count_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;
-    if (classes_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;
-
-       CLASSCACHE_LOCK();
-       *classes_ptr = 
-               heap_allocate(sizeof(jclass)*(hashtable_classcache.entries),true,NULL);
-       
-       /*      look in every slot of the hashtable */
-       for (i=0; i<hashtable_classcache.size; i++) {
-               nameentry = hashtable_classcache.ptr[i];
-               while (nameentry != NULL) { /* iterate over hashlink */
-
-                       /* filter pseudo classes $NEW$,$NULL$,$ARRAYSTUB$ out */
-                       if (nameentry->name->text[0]=='$')
-                       {
-                               log_println("%s", nameentry->name->text);
-                               *class_count_ptr -= 1;
-                               break;
-                               }
+    if (class_count_ptr == NULL)
+               return JVMTI_ERROR_NULL_POINTER;
 
-                       classentry = nameentry->classes;
-                       while (classentry != NULL){ /* iterate over classes with same name */
-                               if (classentry->classobj != NULL) { /*get only loaded classes */
-                                        assert(j<hashtable_classcache.entries);
-                                       (*classes_ptr)[j]=classentry->classobj;
-                                       j++;
-                               }
-                               classentry = classentry->next;
-                       }
-                       nameentry = nameentry->hashlink;
-               }
-       }
-       CLASSCACHE_UNLOCK();
+    if (classes_ptr == NULL)
+               return JVMTI_ERROR_NULL_POINTER;
 
-       *class_count_ptr = j;
+       classcache_jvmti_GetLoadedClasses(class_count_ptr, classes_ptr);
 
     return JVMTI_ERROR_NONE;
 }
@@ -2577,8 +2653,8 @@ GetClassLoaderClasses (jvmtiEnv * env, jobject initiating_loader,
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
 
-/*    if (class_count_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;
-         if (classes_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;*/
+    if ((class_count_ptr == NULL) || (classes_ptr == NULL)) 
+               return JVMTI_ERROR_NULL_POINTER;
         
        /* behave like jdk 1.1 and make no distinction between initiating and 
           defining class loaders */
@@ -2622,6 +2698,7 @@ RedefineClasses (jvmtiEnv * env, jint class_count,
     CHECK_PHASE_END;
        CHECK_CAPABILITY(env,can_redefine_classes)    
        CHECK_CAPABILITY(env,can_redefine_any_class)
+
   log_text ("JVMTI-Call: OPTIONAL IMPLEMENT ME!!!");
     return JVMTI_ERROR_NONE;
 }
@@ -2705,8 +2782,8 @@ IsMethodObsolete (jvmtiEnv * env, jmethodID method,
 
 
 /* SuspendThreadList **********************************************************
-
    
+   Suspend all threads in the request list.
 
 *******************************************************************************/
 
@@ -2714,13 +2791,31 @@ static jvmtiError
 SuspendThreadList (jvmtiEnv * env, jint request_count,
                   const jthread * request_list, jvmtiError * results)
 {
+       int i;
+       int suspendme = -1;
+       jthread me;
+
     CHECK_PHASE_START
     CHECK_PHASE(JVMTI_PHASE_START)
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
     CHECK_CAPABILITY(env,can_suspend);
-        
-       log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!");
+    
+       if (request_count<0) return JVMTI_ERROR_ILLEGAL_ARGUMENT;
+       if ((request_list == NULL) || (results == NULL)) 
+               return JVMTI_ERROR_NULL_POINTER;
+
+       me = jvmti_get_current_thread();
+
+       for (i=0;i<request_count;i++) {
+               if (request_list[i] == me) 
+                       suspendme = i;
+               else 
+                       results[i]=SuspendThread(env, request_list[i]);
+       }
+
+       if (suspendme != -1) 
+               results[suspendme]=SuspendThread(env, request_list[suspendme]);
 
     return JVMTI_ERROR_NONE;
 }
@@ -2728,7 +2823,7 @@ SuspendThreadList (jvmtiEnv * env, jint request_count,
 
 /* ResumeThreadList ***********************************************************
 
-   
+   Resumes all threads in the request list.   
 
 *******************************************************************************/
 
@@ -2736,12 +2831,19 @@ static jvmtiError
 ResumeThreadList (jvmtiEnv * env, jint request_count,
                  const jthread * request_list, jvmtiError * results)
 {
+       int i;
+
        CHECK_PHASE_START
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
     CHECK_CAPABILITY(env,can_suspend);
-        
-       log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!");
+    
+       if (request_count<0) return JVMTI_ERROR_ILLEGAL_ARGUMENT;
+       if ((request_list == NULL) || (results == NULL)) 
+               return JVMTI_ERROR_NULL_POINTER;
+
+       for (i=0;i<request_count;i++) 
+                       results[i]=ResumeThread(env, request_list[i]);
 
     return JVMTI_ERROR_NONE;
 }
@@ -2766,10 +2868,12 @@ GetStackTrace (jvmtiEnv * env, jthread thread, jint start_depth,
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
     
-       if(!builtin_instanceof(thread,class_java_lang_Thread))
-               return JVMTI_ERROR_INVALID_THREAD;
+       if (thread != NULL){
+               if(!builtin_instanceof(thread,class_java_lang_Thread))
+                       return JVMTI_ERROR_INVALID_THREAD;
 
-       CHECK_THREAD_IS_ALIVE(thread);
+               CHECK_THREAD_IS_ALIVE(thread);
+       }
 
        if((count_ptr == NULL)||(frame_buffer == NULL)) 
                return JVMTI_ERROR_NULL_POINTER;
@@ -2777,16 +2881,21 @@ GetStackTrace (jvmtiEnv * env, jthread thread, jint start_depth,
        if (max_frame_count <0) return JVMTI_ERROR_ILLEGAL_ARGUMENT;
 
        er = getcacaostacktrace(&trace, thread);
-       if (er==JVMTI_ERROR_NONE) return er;
+       if (er == JVMTI_ERROR_NONE) {
+               heap_free(trace);
+               return er;
+       }
 
        if ((trace->used >= start_depth) || ((trace->used * -1) > start_depth)) 
                return JVMTI_ERROR_ILLEGAL_ARGUMENT; 
        
        for (i=start_depth, j=0;i<trace->used;i++,j++) {
                frame_buffer[j].method = (jmethodID)trace->entries[i].method;
-        /* todo: location BCI/MachinePC not avilable - Linenumber not expected */
+        /* XXX todo: location BCI/MachinePC not avilable - Linenumber not expected */
                frame_buffer[j].location = 0;
                }
+
+       heap_free(trace);
        
     return JVMTI_ERROR_NONE;
 }
@@ -2856,15 +2965,12 @@ GetAllStackTraces (jvmtiEnv * env, jint max_frame_count,
     
        if (thread_count_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;
     
-       /* todo: all threads have to be suspended */ 
-
        if (JVMTI_ERROR_NONE!=GetAllThreads(env,thread_count_ptr,&threads_ptr))
                return JVMTI_ERROR_INTERNAL;
 
        GetThreadListStackTraces(env, *thread_count_ptr, threads_ptr,
                                                         max_frame_count, stack_info_ptr);
 
-       /* todo: resume all threads have to be suspended */ 
        if (er != JVMTI_ERROR_NONE) return er;
 
     return JVMTI_ERROR_NONE;
@@ -3194,6 +3300,7 @@ SetEventCallbacks (jvmtiEnv * env,
 
     if (size_of_callbacks < 0) return JVMTI_ERROR_ILLEGAL_ARGUMENT;
 
+
        if (callbacks == NULL) { /* remove the existing callbacks */
         memset(&(((environment* )env)->callbacks), 0, 
                           sizeof(jvmtiEventCallbacks));
@@ -3218,8 +3325,8 @@ GenerateEvents (jvmtiEnv * env, jvmtiEvent event_type)
     CHECK_PHASE_START
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
-        
-  log_text ("JVMTI-Call: IMPLEMENT ME!!!");
+       CHECK_CAPABILITY(env,can_generate_compiled_method_load_events);
+
     return JVMTI_ERROR_NONE;
 }
 
@@ -3239,7 +3346,7 @@ GetExtensionFunctions (jvmtiEnv * env, jint * extension_count_ptr,
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
         
-    if ((extension_count_ptr== NULL)||(extensions == NULL)) 
+    if ((extension_count_ptr == NULL)||(extensions == NULL)) 
         return JVMTI_ERROR_NULL_POINTER;
 
     /* cacao has no extended functions yet */
@@ -3264,7 +3371,7 @@ GetExtensionEvents (jvmtiEnv * env, jint * extension_count_ptr,
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
         
-    if ((extension_count_ptr== NULL)||(extensions == NULL)) 
+    if ((extension_count_ptr == NULL)||(extensions == NULL)) 
         return JVMTI_ERROR_NULL_POINTER;
 
     /* cacao has no extended events yet */
@@ -3465,7 +3572,7 @@ GetErrorName (jvmtiEnv * env, jvmtiError error, char **name_ptr)
 static jvmtiError
 GetJLocationFormat (jvmtiEnv * env, jvmtiJlocationFormat * format_ptr)
 {
-    *format_ptr = JVMTI_JLOCATION_MACHINEPC;
+    *format_ptr = JVMTI_JLOCATION_OTHER;
     return JVMTI_ERROR_NONE;
 }
 
@@ -3788,8 +3895,7 @@ GetTime (jvmtiEnv * env, jlong * nanos_ptr)
 *******************************************************************************/
 
 static jvmtiError
-GetPotentialCapabilities (jvmtiEnv * env,
-                         jvmtiCapabilities * capabilities_ptr)
+GetPotentialCapabilities (jvmtiEnv * env, jvmtiCapabilities * capabilities_ptr)
 {
     CHECK_PHASE_START
     CHECK_PHASE(JVMTI_PHASE_ONLOAD)
@@ -3936,9 +4042,9 @@ RelinquishCapabilities (jvmtiEnv * env,
     return JVMTI_ERROR_NONE;
 }
 
-/* *****************************************************************************
+/* GetAvailableProcessors *****************************************************
 
-   
+   Get number of processors available to the virtual machine.
 
 *******************************************************************************/
 
@@ -4106,18 +4212,18 @@ static jvmtiCapabilities JVMTI_Capabilities = {
   0,                           /* can_access_local_variables */
   0,                           /* can_maintain_original_method_order */
   0,                           /* can_generate_single_step_events */
-  0,                           /* can_generate_exception_events */
+  1,                           /* can_generate_exception_events */
   0,                           /* can_generate_frame_pop_events */
-  0,                           /* can_generate_breakpoint_events */
-  0,                           /* can_suspend */
+  1,                           /* can_generate_breakpoint_events */
+  1,                           /* can_suspend */
   0,                           /* can_redefine_any_class */
   0,                           /* can_get_current_thread_cpu_time */
   0,                           /* can_get_thread_cpu_time */
-  0,                           /* can_generate_method_entry_events */
+  1,                           /* can_generate_method_entry_events */
   0,                           /* can_generate_method_exit_events */
   0,                           /* can_generate_all_class_hook_events */
   0,                           /* can_generate_compiled_method_load_events */
-  0,                           /* can_generate_monitor_events */
+  1,                           /* can_generate_monitor_events */
   0,                           /* can_generate_vm_object_alloc_events */
   0,                           /* can_generate_native_method_bind_events */
   0,                           /* can_generate_garbage_collection_events */
@@ -4281,6 +4387,11 @@ static struct jvmtiEnv_struct JVMTI_EnvTable = {
     &GetObjectSize
 };
 
+/* jvmti_set_phase ************************************************************
+
+  sets a new jvmti phase a fires an apropriate event.
+
+*******************************************************************************/
 
 void jvmti_set_phase(jvmtiPhase p) {
        genericEventData d;
@@ -4318,6 +4429,13 @@ void jvmti_set_phase(jvmtiPhase p) {
        jvmti_fireEvent(&d);
 }
 
+
+/* jvmti_new_environment ******************************************************
+
+  creates a new JVMTI environment
+
+*******************************************************************************/
+
 jvmtiEnv* jvmti_new_environment() {
     environment* env;
 
@@ -4347,30 +4465,50 @@ jvmtiEnv* jvmti_new_environment() {
        return (jvmtiEnv*)env;
 }
 
+/* jvmti_agentload ************************************************************
+
+  loads the indicated shared library containing the jvmti agent and calls the
+  Agent_OnLoad function.
+
+*******************************************************************************/
+
 void jvmti_agentload(char* opt_arg, bool agentbypath, lt_dlhandle  *handle, char **libname) {
        lt_ptr onload;
        char *arg;
        int i=0,len;
        jint retval;
 
-       
        len = strlen(opt_arg);
        
-       /* separate argumtents */
-       while ((opt_arg[i]!='=')&&(i<=len)) i++;
-       arg = &opt_arg[i];
+       /* separate arguments */
+
+       while ((opt_arg[i] != '=') && (i < len))
+               i++;
+
+       opt_arg[i] = '\0';
+
+       if (i < len)
+               arg = &opt_arg[i + 1];
+       else
+               arg = "";
 
        if (agentbypath) {
                /* -agentpath */
-               *libname=heap_allocate(sizeof(char)*i,true,NULL);
-               strncpy(*libname,opt_arg,i-1);
-               (*libname)[i-1]='\0';
-       } else {
+
+               *libname = GCMNEW(char, i);
+
+               strcpy(*libname, opt_arg);
+       }
+       else {
                /* -agentlib */
-               *libname=heap_allocate(sizeof(char)*(i+7),true,NULL);
-               strncpy(*libname,"lib",3);
-               strncpy(&(*libname)[3],opt_arg,i-1);
-               strncpy(&(*libname)[i+2],".so",3);
+
+               len = strlen("lib") + i + strlen(".so") + strlen("0");
+
+               *libname = GCMNEW(char, len);
+
+               strcpy(*libname, "lib");
+               strcat(*libname, opt_arg);
+               strcat(*libname, ".so");
        }
 
        /* try to open the library */
@@ -4396,6 +4534,12 @@ void jvmti_agentload(char* opt_arg, bool agentbypath, lt_dlhandle  *handle, char
        if (retval != 0) exit (retval);
 }
 
+/* jvmti_agentunload **********************************************************
+
+  calls the Agent_UnLoad function in the jvmti agent if present.
+
+*******************************************************************************/
+
 void jvmti_agentunload() {
        if (unload != NULL) {
                ((JNIEXPORT void JNICALL (*) (JavaVM *vm)) unload) 
@@ -4403,6 +4547,7 @@ void jvmti_agentunload() {
        }
 }
 
+
 /*
  * These are local overrides for various environment variables in Emacs.
  * Please do not remove this and leave it at the end of the file, where