src/native/vm/VMVirtualMachine.c (suspendThread): print error message with printjvmti...
[cacao.git] / src / native / jvmti / jvmti.c
index 97552b381dce3ec3e8888f0604f94d7908aa5faa..fa88ca11607f52e1d28e1ed9ffae30cbac63a5af 100644 (file)
@@ -31,7 +31,7 @@
             Samuel Vinson
 
    
-   $Id: jvmti.c 4944 2006-05-23 15:31:19Z motse $
+   $Id: jvmti.c 4996 2006-05-31 13:53:16Z motse $
 
 */
 
@@ -41,6 +41,7 @@
 #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"
@@ -64,7 +65,7 @@
 #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 "boehm-gc/include/gc.h"
 
 #include <string.h>
 #include <linux/unistd.h>
@@ -125,10 +126,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;
 
 
@@ -584,9 +586,17 @@ 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);
 
+
+       /* quick try - this should be changed in the future */
+       pthread_kill(((threadobject*)((java_lang_Thread*) thread)->vmThread)->tid,
+                                GC_signum1());
+       
+       
     return JVMTI_ERROR_NONE;
 }
 
@@ -604,8 +614,15 @@ 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);
+
+
+       /* quick try - this should be changed in the future */
+       pthread_kill(((threadobject*)((java_lang_Thread*) thread)->vmThread)->tid,
+                                GC_signum2());
 
     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_interrupt_thread(((java_lang_Thread*)thread)->vmThread);
+
 
     return JVMTI_ERROR_NONE;
+#else
+       return JVMTI_ERROR_NOT_AVAILABLE;
+#endif
 }
 
 /* GetThreadInfo ***************************************************************
@@ -667,16 +687,22 @@ 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;
 }
@@ -695,6 +721,7 @@ GetOwnedMonitorInfo (jvmtiEnv * env, jthread thread,
        int i,j,size=20;
        java_objectheader **om;
        lock_record_pool_t* lrp;
+       threadobject* t;
 
        log_text("GetOwnedMonitorInfo called");
 
@@ -706,10 +733,15 @@ GetOwnedMonitorInfo (jvmtiEnv * env, jthread thread,
        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)
 
@@ -720,7 +752,7 @@ GetOwnedMonitorInfo (jvmtiEnv * env, jthread thread,
 
        while (lrp != NULL) {
                for (j=0; j<lrp->header.size; j++) {
-/*                     if((lrp->lr[j].owner==(threadobject*)thread)&&
+/*                     if((lrp->lr[j].owner==t)&&
                           (!lrp->lr[j].waiting)) {
                                if (i>=size) {
                                        MREALLOC(om,java_objectheader*,size,size*2);
@@ -840,7 +872,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;
@@ -1001,14 +1033,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*));
@@ -1025,13 +1059,18 @@ GetThreadGroupChildren (jvmtiEnv * env, jthreadGroup group,
 *******************************************************************************/
 static jvmtiError getcacaostacktrace(stacktracebuffer** trace, jthread thread) {
        threadobject *t;
+       
+       if (thread == NULL)
+               t = jvmti_get_current_thread();
+       else {
+               t = (threadobject*)((java_lang_Thread*)thread)->vmThread;
+               if (t != jvmti_get_current_thread())
+                       /* XXX: todo: take care that the requested thread is in a 
+                          safe state - this needs a working thread suspend */
+                       return JVMTI_ERROR_INTERNAL;
+       }
 
-       log_text("getcacaostacktrace");
-
-       t = (threadobject*)((java_lang_Thread*)thread)->vmThread;
-
-/*      XXX todo
- *trace = stacktrace_create(t); */
+       *trace = stacktrace_create(t);
 
     return JVMTI_ERROR_NONE;
 }
@@ -1054,18 +1093,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;
 }
 
@@ -1101,7 +1146,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 +1178,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)) {
@@ -1433,7 +1484,7 @@ DestroyRawMonitor (jvmtiEnv * env, jrawMonitorID monitor)
        
        lock_monitor_exit((threadobject*)THREADOBJECT, (java_objectheader*)monitor->name);
 
-       /* GC will clean monitor up */
+       heap_free(monitor);
 #else
        log_text ("DestroyRawMonitor not supported");
 #endif
@@ -1735,30 +1786,25 @@ static jvmtiError
 GetClassSignature (jvmtiEnv * env, jclass klass, char **signature_ptr,
                   char **generic_ptr)
 {
-    int nsize,psize;
-
     CHECK_PHASE_START
     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;
-
-    nsize=((classinfo*)klass)->name->blength;
-    psize=((classinfo*)klass)->packagename->blength;
-
-    *signature_ptr = (char*) 
-        heap_allocate(sizeof(char)* nsize+psize+4,true,NULL);
+    
+       if (klass == NULL) return JVMTI_ERROR_INVALID_CLASS;
+       if (!builtin_instanceof(klass,class_java_lang_Class))
+               return JVMTI_ERROR_INVALID_CLASS;
 
-    *signature_ptr[0]='L';
-    memcpy(&(*signature_ptr[1]),((classinfo*)klass)->packagename->text, psize);
-    *signature_ptr[psize+2]='/';
-    memcpy(&(*signature_ptr[psize+3]),((classinfo*)klass)->name->text, nsize);
-    *signature_ptr[nsize+psize+3]=';';
-    *signature_ptr[nsize+psize+4]='\0';
+       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);
+       }
 
-    *generic_ptr = NULL;
+       if (generic_ptr!= NULL)
+               *generic_ptr = NULL;
 
     return JVMTI_ERROR_NONE;
 }
@@ -1788,13 +1834,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) 
@@ -1827,7 +1873,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);
     
@@ -2103,19 +2149,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;
 }
@@ -2137,7 +2193,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;
@@ -2158,14 +2224,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;
@@ -2211,19 +2280,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;
 }
@@ -2362,9 +2437,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;
     }
     
@@ -2402,8 +2477,10 @@ GetMethodLocation (jvmtiEnv * env, jmethodID method,
        /* XXX Don't know if that's the right way to deal with not-yet-
         * compiled methods. -Edwin */
 
+    fprintf(stderr,"GetMethodLocation *** XXX todo \n");
+
        if (!m->code)
-               return JVMTI_ERROR_NULL_POINTER;
+               return JVMTI_ERROR_INTERNAL;
        
     *start_location_ptr = (jlocation)m->code->mcode;
     *end_location_ptr = (jlocation)(m->code->mcode)+m->code->mcodelength;
@@ -2521,18 +2598,9 @@ IsMethodSynthetic (jvmtiEnv * env, jmethodID method,
 static jvmtiError
 GetLoadedClasses (jvmtiEnv * env, jint * class_count_ptr, jclass ** classes_ptr)
 {
-       int i,j;
-       char* data;
-       hashtable* ht;
-       classcache_name_entry *cne;
-       classcache_class_entry *cce;
-
-       log_text ("GetLoadedClasses called %d ", phase);
-
-
-       /* XXX todo */
-
-       *class_count_ptr = 0;
+       int i,j=0;
+       classcache_name_entry *nameentry;
+       classcache_class_entry *classentry;
 
     CHECK_PHASE_START
     CHECK_PHASE(JVMTI_PHASE_LIVE)
@@ -2541,54 +2609,38 @@ GetLoadedClasses (jvmtiEnv * env, jint * class_count_ptr, jclass ** classes_ptr)
     if (class_count_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;
     if (classes_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;
 
-       log_text ("GetLoadedClasses1");
-
-/*
        CLASSCACHE_LOCK();
-       log_text ("GetLoadedClasses2");
-       getchildproc(&data, &hashtable_classcache, sizeof(hashtable));
-       ht = (hashtable*) &data;
-
-       log_text ("GetLoadedClasses got ht pointer");
        *classes_ptr = 
-               heap_allocate(sizeof(jclass*) * (ht->entries),true,NULL);
-       fprintf (stderr,"hashtable_classcache.entries = %d\n",ht->entries);
-       fflush(stderr);
+               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]=='$')
+                       {
+                               *class_count_ptr -= 1;
+                               break;
+                       }
 
-       *class_count_ptr = ht->entries;
-       log_text ("GetLoadedClasses %d", *class_count_ptr);
-       j=0;
-     look in every slot of the hashtable 
-       for (i=0; i<ht->size; i++) { 
-               cne = ht->ptr[i];
-
-               while (cne != NULL) { iterate over hashlink 
-                       getchildproc(&data, cne, sizeof(classcache_name_entry));
-                       cne =(classcache_name_entry*) &data;
-
-                       cce = cne->classes;
-                       while (cce != NULL){ iterate over classes with same name 
-                               getchildproc(&data, cce, sizeof(classcache_class_entry));
-                               cce =(classcache_class_entry*) &data;
-                                
-                               if (cce->classobj != NULL) { get only loaded classes 
-                                        assert(j<ht->entries);
-                                       * classes_ptr[j]=cce->classobj;
+                       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++;
                                }
-                               cce = cce->next;
+                               classentry = classentry->next;
                        }
-                       cne = cne->hashlink;
+                       nameentry = nameentry->hashlink;
                }
        }
  
-       log_text ("GetLoadedClasses continue");
-
        CLASSCACHE_UNLOCK();
 
-*/
-
-       log_text ("GetLoadedClasses finished");
+       *class_count_ptr = j;
 
     return JVMTI_ERROR_NONE;
 }
@@ -2611,8 +2663,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 */
@@ -2656,6 +2708,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;
 }
@@ -2739,8 +2792,8 @@ IsMethodObsolete (jvmtiEnv * env, jmethodID method,
 
 
 /* SuspendThreadList **********************************************************
-
    
+   Suspend all threads in the request list.
 
 *******************************************************************************/
 
@@ -2748,13 +2801,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;
 }
@@ -2762,7 +2833,7 @@ SuspendThreadList (jvmtiEnv * env, jint request_count,
 
 /* ResumeThreadList ***********************************************************
 
-   
+   Resumes all threads in the request list.   
 
 *******************************************************************************/
 
@@ -2770,12 +2841,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;
 }
@@ -2800,10 +2878,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;
@@ -2811,16 +2891,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;
 }
@@ -2890,15 +2975,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;
@@ -3228,6 +3310,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));
@@ -3252,8 +3335,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;
 }
 
@@ -3822,8 +3905,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)
@@ -3970,9 +4052,9 @@ RelinquishCapabilities (jvmtiEnv * env,
     return JVMTI_ERROR_NONE;
 }
 
-/* *****************************************************************************
+/* GetAvailableProcessors *****************************************************
 
-   
+   Get number of processors available to the virtual machine.
 
 *******************************************************************************/
 
@@ -4143,7 +4225,7 @@ static jvmtiCapabilities JVMTI_Capabilities = {
   0,                           /* can_generate_exception_events */
   0,                           /* can_generate_frame_pop_events */
   0,                           /* can_generate_breakpoint_events */
-  0,                           /* can_suspend */
+  1,                           /* can_suspend */
   0,                           /* can_redefine_any_class */
   0,                           /* can_get_current_thread_cpu_time */
   0,                           /* can_get_thread_cpu_time */
@@ -4387,24 +4469,26 @@ void jvmti_agentload(char* opt_arg, bool agentbypath, lt_dlhandle  *handle, char
        int i=0,len;
        jint retval;
 
-       
        len = strlen(opt_arg);
        
        /* separate argumtents */
-       while ((opt_arg[i]!='=')&&(i<=len)) i++;
-       arg = &opt_arg[i];
+       while ((opt_arg[i]!='=')&&(i<len)) i++;
+       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';
+               strncpy(*libname,opt_arg,i);
+               (*libname)[i]='\0';
        } 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);
+               strncpy(&(*libname)[3],opt_arg,i);
+               strncpy(&(*libname)[i+3],".so",3);
        }
 
        /* try to open the library */