Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 尝试使用jvmti访问异常和线程对象的值时出现无效插槽错误_Java_Java Native Interface_Jvmti - Fatal编程技术网

Java 尝试使用jvmti访问异常和线程对象的值时出现无效插槽错误

Java 尝试使用jvmti访问异常和线程对象的值时出现无效插槽错误,java,java-native-interface,jvmti,Java,Java Native Interface,Jvmti,我有下面的java程序,当使用JVMTI发生异常时,我试图使用它捕获方法中变量的状态 public class SimpleThread{ static MyThread t; String thisThread = "this Thread"; public static void main(String[] args) throws Exception { Thread thr = new Thread(new Runnable() {

我有下面的java程序,当使用JVMTI发生异常时,我试图使用它捕获方法中变量的状态

public class SimpleThread{
    static MyThread t;
    String thisThread = "this Thread";
    public static void main(String[] args) throws Exception {
            Thread thr = new Thread(new Runnable() {
                    final Exception exec = new IllegalArgumentException("Titanic");
                    public void run() {
                            // while(true) {
                            String firstString = "string";
                            int firstInt = 1;
                            for (int i =0 ; i <=3; i++) {
                                    try {
                                            throw exec;
                                    } catch(Exception e) {
                                            e.printStackTrace();
                                    }
                            }
                            // }
                    }
            });

            thr.start();
    }
}
我得到以下输出

Trying to fetch value of e
JNIException (java/lang/AssertionError): 'Unable to get local value; JVMTI      ERROR: '35' (JVMTI_ERROR_INVALID_SLOT)' 
当它试图获取MyThread t的信息时,也会发生同样的情况 我哪里做错了

代理代码如下:

#include<jni.h>
#include<jvmti.h>
#include<string.h>
#include<stdlib.h>
#include<stdbool.h>
typedef struct {
jvmtiEnv *jvmti;
jrawMonitorID lock;
} GlobalAgentData;

static GlobalAgentData *gdata;

static bool check_jvmti_error(jvmtiEnv *jvmti,jvmtiError errnum,const char *str){
if(errnum != JVMTI_ERROR_NONE){
    char *errnum_str;
    errnum_str = NULL;
    if(errnum!=JVMTI_ERROR_ABSENT_INFORMATION){
    (void)(*jvmti)->GetErrorName(jvmti,errnum,&errnum_str);
    printf("ERROR: JVMTI: %d(%s): %s\n", errnum, 
    (errnum_str==NULL?"Unknown":errnum_str),
    (str==NULL?"":str));

 }
 return false;
}
return true;
}

static void deallocate(jvmtiEnv *jvmti,void *ptr){
jvmtiError error;
error = (*jvmti)->Deallocate(jvmti,ptr);
check_jvmti_error(jvmti,error,"Cannot deallocate memory");
}

static void allocate(jvmtiEnv *jvmti,jint len){
jvmtiError error;
void *ptr;
error = (*jvmti)->Allocate(jvmti,len,(unsigned char **)&ptr);
check_jvmti_error(jvmti,error,"Cannot allocate memory");
}


JNICALL jint objectCountingCallback(jlong class_tag,jlong size,jlong* tag_ptr,jint length,void* user_data){
    int* count = (int*)user_data;
    *count+=1;
    return JVMTI_VISIT_OBJECTS;
}

JNICALL jint stringPrimitiveValueCallback(jlong class_tag,jlong size,jlong* tag_ptr,const jchar* value,jint value_length,void* user_data){
printf("Inside String primitive call back\n");
printf("%s\n",(char*)value);
return JVMTI_VISIT_OBJECTS;
}


JNICALL jint primitiveFieldCallBack(jvmtiHeapReferenceKind kind,const jvmtiHeapReferenceInfo* info,jlong object_class_tag,jlong* object_tag_ptr,jvalue value,jvmtiPrimitiveType value_type,void *user_data){
printf("Inside Primitive field callback\n");
switch(value_type){
    case 90 : {
                printf("%d\n",value.z);
                break;
    }
    case 66 : {
                printf("%d\n",value.b);
                break;
    }
    case 67 : {
                printf("%c\n",value.c);
                break;
    }
    case 83 : {
                printf("%d\n",value.s);
                break;
    }
    case 73 : {
                printf("%d\n",value.i);
                break;
    }
    case 74 : {
                printf("%ld\n",value.j);
                break;
    }
    case 70 : {
                printf("%f\n",value.f);
                break;
    }
    case 68 : {
                printf("%f\n",value.d);
                break;
    }
}
return JVMTI_VISIT_OBJECTS;
}


JNIEXPORT jint JNICALL Java_Test_countInstances(JNIEnv *env,jclass thisClass,jclass klass){
    int count =0 ;
    jvmtiError error;
    jvmtiHeapCallbacks callbacks;
jvmtiEnv *jvmti;
    (void)memset(&callbacks,0,sizeof(callbacks));
    callbacks.heap_iteration_callback = &objectCountingCallback;
    jvmti = gdata->jvmti;
error = (*jvmti)->IterateThroughHeap(jvmti,0,klass,&callbacks,&count);
//  check_jvmti_error(*gdata->jvmti,error,"Unable to iterate through the heap");
    return count;
}

static void enter_critical_section(jvmtiEnv *jvmti){
jvmtiError error;
error = (*jvmti)->RawMonitorEnter(jvmti,gdata->lock);
check_jvmti_error(jvmti,error,"Cannot enter with raw monitor");
}

static void exit_critical_section(jvmtiEnv *jvmti){
jvmtiError error;
error = (*jvmti)->RawMonitorExit(jvmti,gdata->lock);
check_jvmti_error(jvmti,error,"Cannot exit with raw monitor");
}

static void JNICALL callbackVMInit(jvmtiEnv *jvmti,JNIEnv *env,jthread thread){
jvmtiError error;
//  enter_critical_section(jvmti);{ /* not needed since we are just setting event notifications */
printf("Initializing JVM\n");
error = (*jvmti)->SetEventNotificationMode(jvmti,JVMTI_ENABLE,JVMTI_EVENT_EXCEPTION,(jthread)NULL);
//  error = (*jvmti)->SetEventNotificationMode(jvmti,JVMTI_ENABLE,JVMTI_EVENT_METHOD_ENTRY,(jthread)NULL);
check_jvmti_error(jvmti,error,"Cannot set Exception Event notification");
//  } exit_critical_section(jvmti);
}



static void JNICALL callbackException(jvmtiEnv *jvmti, JNIEnv *env,
    jthread thread, jmethodID method, jlocation location, jobject exception,
    jmethodID catch_method, jlocation catch_location) {
jvmtiFrameInfo frames[10];
jint count, entry_count_ptr;
int i, j;
jvmtiError error;
char *sig, *gsig,*methodName,*className;
jclass declaring_class_ptr;
jvmtiLocalVariableEntry *table_ptr;

error = (*jvmti)->GetStackTrace(jvmti, thread, 0, 10, frames, &count);
if (check_jvmti_error(jvmti, error, "Cannot Get Frame") && count >= 1) {
    for (i = 0; i < count; i++) {
        error = (*jvmti)->GetMethodName(jvmti, frames[i].method,
                &methodName, &sig, &gsig);
        if (check_jvmti_error(jvmti, error, "Cannot Get method name")) {

            error = (*jvmti)->GetMethodDeclaringClass(jvmti,
                    frames[i].method, &declaring_class_ptr);
            check_jvmti_error(jvmti, error,
                    "Cannot Get method declaring class");

            error = (*jvmti)->GetClassSignature(jvmti, declaring_class_ptr,
                    &className, NULL);
            check_jvmti_error(jvmti, error, "Cannot get class signature");

            error = (*jvmti)->GetLocalVariableTable(jvmti, frames[i].method,
                    &entry_count_ptr, &table_ptr);
            check_jvmti_error(jvmti, error,
                    "Cannot Get Local Variable Table");

            if (strstr(className, "java") == NULL
                    && strstr(className, "javax") == NULL   
                    && strstr(className, "sun") == NULL) {
                printf(
                    "Got Exception in  Method: %s at Line: %ld with Signature:%s,%s within Class:%s\n",
                    methodName, frames[i].location, sig, gsig, className);

                for (j = 0; j < entry_count_ptr; j++) {
                    printf("Field Signature:%s\n", table_ptr[j].signature);
                    switch (*(table_ptr[j].signature)) {
                    case 'B': {
                        jint value_ptr;
                        error = (*jvmti)->GetLocalInt(jvmti, thread, i,
                                table_ptr[j].slot, &value_ptr);
                        check_jvmti_error(jvmti, error,
                                "Cannot Get Local Variable Byte");

                        printf("Value of Field %s is %d.\n", table_ptr[j].name, (jbyte)value_ptr);
                        break;
                    }

                    case 'C': {
                        jint value_ptr;
                        error = (*jvmti)->GetLocalInt(jvmti, thread, i,
                                table_ptr[j].slot, &value_ptr);
                        check_jvmti_error(jvmti, error,
                                "Cannot Get Local Variable Char");

                        printf("Value of Field %s is %c.\n", table_ptr[j].name, (jchar)value_ptr);
                        break;
                    }
                    case 'D': {
                        jdouble value_ptr;
                        error = (*jvmti)->GetLocalDouble(jvmti, thread, i,
                                table_ptr[j].slot, &value_ptr);
                        check_jvmti_error(jvmti, error,
                                "Cannot Get Local Variable Double");

                        printf("Value of Field %s is %f.\n", table_ptr[j].name, value_ptr);
                        break;
                    }
                    case 'F': {
                        jfloat value_ptr;
                        error = (*jvmti)->GetLocalFloat(jvmti, thread, i,
                                table_ptr[j].slot, &value_ptr);
                        check_jvmti_error(jvmti, error,
                                "Cannot Get Local Variable Float");

                        printf("Value of Field %s is %f.\n", table_ptr[j].name, value_ptr);
                        break;
                    }
                    case 'I': {
                        jint value_ptr;
                        error = (*jvmti)->GetLocalInt(jvmti, thread, i,
                                table_ptr[j].slot, &value_ptr);
                        check_jvmti_error(jvmti, error,
                                "Cannot Get Local Variable Integer");

                        printf("Value of Field %s is %d.\n", table_ptr[j].name, value_ptr);
                        break;
                    }
                    case 'J': {
                        jlong value_ptr;
                        error = (*jvmti)->GetLocalLong(jvmti, thread, i,
                                table_ptr[j].slot, &value_ptr);
                        check_jvmti_error(jvmti, error,
                                "Cannot Get Local Variable Long");

                        printf("Value of Field %s is %ld.\n", table_ptr[j].name, value_ptr);
                        break;
                    }
                    case 'S':{
                        jint value_ptr;
                        error = (*jvmti)->GetLocalInt(jvmti, thread, i,
                                table_ptr[j].slot, &value_ptr);
                        check_jvmti_error(jvmti, error,
                                "Cannot Get Local Variable Short");

                        printf("Value of Field %s is %d.\n", table_ptr[j].name, (jshort)value_ptr);
                        break;
                    }
                    case 'Z':{
                        jint value_ptr;
                        error = (*jvmti)->GetLocalInt(jvmti, thread, i,
                                table_ptr[j].slot, &value_ptr);
                        check_jvmti_error(jvmti, error,
                                "Cannot Get Local Variable Boolean");

                        printf("Value of Field %s is %d.\n", table_ptr[j].name, (jboolean)value_ptr);
                        break;
                    }
                    case 'L':{
                        int count=0;
                        jobject value_ptr;
                        jclass klaz;
                        jfieldID field;
                        jstring value;
                        const char *stringVal;
                        jvmtiHeapCallbacks callbacks;
                        // (void)memset(&callbacks,0,sizeof(callbacks));
                        // callbacks.primitive_field_callback = &primitiveFieldCallBack;
                        // callbacks.string_primitive_value_callback = &stringPrimitiveValueCallback;
                        // if(strcmp(table_ptr[j].name,"this")==0){
                         // printf("Iterating through primitive fields of this object\n");  
                         error = (*jvmti)->GetLocalObject(jvmti, thread, i,table_ptr[j].slot, &value_ptr);
                         check_jvmti_error(jvmti, error,"Cannot Get Local Variable Object");
                        //  error =    (*jvmti)->IterateThroughHeap(jvmti,0,declaring_class_ptr,&callbacks,&count);
                        //  error = (*jvmti)->FollowReferences(jvmti,0,declaring_class_ptr,value_ptr,&callbacks,&count);
                        // }


                    //  char *klazName;
                    //  error = (*jvmti)->GetLocalObject(jvmti, thread, i,
                    //          table_ptr[j].slot, &value_ptr);
                    //  check_jvmti_error(jvmti, error,
                    //          "Cannot Get Local Variable Object");
                    //  if(!error){
                    //      klaz = (*env)->GetObjectClass(env,value_ptr);
                    //      error = (*jvmti)->GetClassSignature(jvmti, klaz,
                    // &klazName, NULL);
                    //      if(strstr(klazName,"String")!=NULL){
                    //          printf("...%s\n",klazName);
                    //          field = (*env)->GetFieldID(env,declaring_class_ptr,table_ptr[j].name,"S");
                    //          value = (jstring)(*env)->GetObjectField(env,value_ptr,field);
                    //          stringVal = (*env)->GetStringUTFChars(env,value,0);
                    //          printf("Value of Field %s is .\n", stringVal);
                            }
                        }


                        printf("Value of Field %s is .\n", table_ptr[j].name);
                        break;
                    }
                    case '[':{
                        printf("This is an array reference \n");
                        printf("Value of Field %s is .\n", table_ptr[j].name);  
                        break;
                    }
                    default:
                        printf("Can't get %s type.\n",
                                table_ptr[j].signature);
                    }

                }
            }

        }
    }
 }

 }



JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm,char *options,void *reserved){
jvmtiEnv *jvmti;
jvmtiCapabilities capabilities;
jvmtiError error;
jint result;
jvmtiEventCallbacks callbacks;

result = (*jvm)->GetEnv(jvm,(void **)&jvmti,JVMTI_VERSION_1);
if(result!=JNI_OK){
    printf("Unable to access JVMTI! \n");
}
    gdata = (GlobalAgentData*)malloc(sizeof(GlobalAgentData));
    gdata->jvmti=jvmti;

(void)memset(&capabilities,0,sizeof(jvmtiCapabilities));
capabilities.can_tag_objects = 1;
capabilities.can_signal_thread=1;
capabilities.can_get_owned_monitor_info=1;
capabilities.can_generate_method_entry_events=1;
capabilities.can_generate_exception_events=1;
capabilities.can_access_local_variables=1;

error = (*(gdata->jvmti))->AddCapabilities(gdata->jvmti,&capabilities);
check_jvmti_error(gdata->jvmti,error,"Unable to set Capabilities");  

(void)memset(&callbacks,0,sizeof(callbacks));
callbacks.VMInit = &callbackVMInit;
callbacks.Exception = &callbackException;
//callbacks.MethodEntry = &callbackMethodEntry;

error = (*(gdata->jvmti))->SetEventCallbacks(gdata->jvmti,&callbacks,(jint)sizeof(callbacks));
check_jvmti_error(gdata->jvmti,error,"Cannot set event callbacks");

error = (*(gdata->jvmti))->SetEventNotificationMode(gdata->jvmti,JVMTI_ENABLE,JVMTI_EVENT_VM_INIT,(jthread)NULL);
check_jvmti_error(gdata->jvmti,error,"Cannot set event notification");

error = (*(gdata->jvmti))->CreateRawMonitor(gdata->jvmti,"agent data",&(gdata->lock));
check_jvmti_error(gdata->jvmti,error,"Cannot create raw monitor");

printf("A message from my custom super agent!!\n");
return JNI_OK;
} 
#包括
#包括
#包括
#包括
#包括
类型定义结构{
jvmtiEnv*jvmti;
jrawMonitorID锁;
}全球数据;
静态GlobalAgentData*gdata;
静态布尔检查jvmti错误(jvmtiEnv*jvmti,jvmtiError errnum,const char*str){
如果(errnum!=JVMTI_ERROR_NONE){
char*errnum_str;
errnum_str=NULL;
if(errnum!=JVMTI错误信息){
(void)(*jvmti)->GetErrorName(jvmti、errnum和errnum_str);
printf(“错误:JVMTI:%d(%s):%s\n”,errnum,
(errnum_str==NULL?“未知”:errnum_str),
(str==NULL?“:str”);
}
返回false;
}
返回true;
}
静态无效解除分配(jvmtiEnv*jvmti,无效*ptr){
jvmtiError错误;
错误=(*jvmti)->解除分配(jvmti,ptr);
检查jvmti_错误(jvmti,错误,“无法释放内存”);
}
静态无效分配(jvmtiEnv*jvmti,jint len){
jvmtiError错误;
无效*ptr;
error=(*jvmti)->Allocate(jvmti,len,(unsigned char**)和ptr);
检查jvmti_错误(jvmti,错误,“无法分配内存”);
}
JNICALL jint objectCountingCallback(jlong class_标记、jlong大小、jlong*标记、jint长度、void*用户数据){
int*计数=(int*)用户数据;
*计数+=1;
返回JVMTI_访问_对象;
}
JNICALL jint stringPrimitiveValueCallback(jlong class_标记、jlong大小、jlong*tag_ptr、const jchar*value、jint值_长度、void*user_数据){
printf(“内部字符串原语回调\n”);
printf(“%s\n”,(char*)值);
返回JVMTI_访问_对象;
}
JNICALL jint primitiveFieldCallBack(jvmtiHeapReferenceKind、const jvmtiHeapReferenceInfo*info、jlong对象类标记、jlong*对象标记ptr、jvalue值、jvmtiPrimitiveType值类型、void*用户数据){
printf(“内部原语字段回调\n”);
开关(数值型){
案例90:{
printf(“%d\n”,值.z);
打破
}
案例66:{
printf(“%d\n”,值.b);
打破
}
案例67:{
printf(“%c\n”,value.c);
打破
}
案例83:{
printf(“%d\n”,值为.s);
打破
}
案例73:{
printf(“%d\n”,值.i);
打破
}
案例74:{
printf(“%ld\n”,值.j);
打破
}
案例70:{
printf(“%f\n”,值为.f);
打破
}
案例68:{
printf(“%f\n”,值.d);
打破
}
}
返回JVMTI_访问_对象;
}
JNIEXPORT jint JNICALL Java_Test_countInstances(JNIEnv*env,jclass thisClass,jclass klass){
整数计数=0;
jvmtiError错误;
jvmtiHeapCallbacks回调;
jvmtiEnv*jvmti;
(void)memset(&callbacks,0,sizeof(callbacks));
callbacks.heap\u iteration\u callback=&objectCountingCallback;
jvmti=gdata->jvmti;
error=(*jvmti)->iterateThrowheap(jvmti,0,klass,&callbacks,&count);
//检查jvmti_error(*gdata->jvmti,error,“无法遍历堆”);
返回计数;
}
静态无效输入关键部分(jvmtiEnv*jvmti){
jvmtiError错误;
错误=(*jvmti)->RawMonitorEnter(jvmti,gdata->lock);
检查jvmti错误(jvmti,错误,“无法使用原始监视器输入”);
}
静态无效退出临界段(jvmtiEnv*jvmti){
jvmtiError错误;
错误=(*jvmti)->RawMonitorExit(jvmti,gdata->lock);
检查jvmti_错误(jvmti,错误,“无法使用原始监视器退出”);
}
静态void JNICALL callbackVMInit(jvmtiEnv*jvmti、JNIEnv*env、jthread线程){
jvmtiError错误;
//输入_critical_section(jvmti);{/*不需要,因为我们只是设置事件通知*/
printf(“初始化JVM\n”);
错误=(*jvmti)->SetEventNotificationMode(jvmti,jvmti_启用,jvmti_事件_异常,(jthread)NULL);
//错误=(*jvmti)->SetEventNotificationMode(jvmti,jvmti_启用,jvmti_事件_方法_条目,(jthread)NULL);
检查jvmti_错误(jvmti,错误,“无法设置异常事件通知”);
//}退出临界段(jvmti);
}
静态无效JNICALL回调异常(jvmtiEnv*jvmti、JNIEnv*env、,
jthread线程,jmethodID方法,jlocation位置,jobject异常,
jmethodID catch_方法,jlocation catch_位置){
jvmtiFrameInfo框架[10];
进货清点,进货清点;
int i,j;
jvmtiError错误;
char*sig、*gsig、*methodName、*className;
jclass声明类ptr;
jvmtiLocalVariableEntry*表ptr;
错误=(*jvmti)->GetStackTrace(jvmti、线程、0、10、帧和计数);
if(检查jvmti错误(jvmti,错误,“无法获取帧”)&&count>=1){
对于(i=0;iGetMethodName(jvmti,帧[i]。方法,
&方法名称、&sig、&gsig);
if(检查jvmti_错误(jvmti,错误,“无法获取方法名”)){
错误=(*jvmti)->GetMethodDeclaringClass(jvmti,
框架[i]。方法,声明类(ptr);
检查jvmti错误(jvmti,错误,
“无法获取声明类的方法”);
错误=(*jvmti)->GetClassSignature(jvmti,声明类),
&类名,空);
检查jvmti_错误(jvmti,错误,“无法获取类签名”);
错误=(*jvmti)->GetLocalVariableTable(jvmti,帧[i]。方法,
&条目(计数)(ptr)和表格(ptr);;
检查jvmti错误(jvmti,错误,
“无法获取局部变量表”);
if(strstr(className,“java”)==NULL
&&strstr(类名,“javax”)==NULL
&&strstr(类名,“sun”)==NULL){
printf(
“在方法%s中的第%ld行出现异常,签名为%s,%s在类%s中\n”,
方法名,帧[i]。位置,sig,gsig,类名);
法罗群岛
#include<jni.h>
#include<jvmti.h>
#include<string.h>
#include<stdlib.h>
#include<stdbool.h>
typedef struct {
jvmtiEnv *jvmti;
jrawMonitorID lock;
} GlobalAgentData;

static GlobalAgentData *gdata;

static bool check_jvmti_error(jvmtiEnv *jvmti,jvmtiError errnum,const char *str){
if(errnum != JVMTI_ERROR_NONE){
    char *errnum_str;
    errnum_str = NULL;
    if(errnum!=JVMTI_ERROR_ABSENT_INFORMATION){
    (void)(*jvmti)->GetErrorName(jvmti,errnum,&errnum_str);
    printf("ERROR: JVMTI: %d(%s): %s\n", errnum, 
    (errnum_str==NULL?"Unknown":errnum_str),
    (str==NULL?"":str));

 }
 return false;
}
return true;
}

static void deallocate(jvmtiEnv *jvmti,void *ptr){
jvmtiError error;
error = (*jvmti)->Deallocate(jvmti,ptr);
check_jvmti_error(jvmti,error,"Cannot deallocate memory");
}

static void allocate(jvmtiEnv *jvmti,jint len){
jvmtiError error;
void *ptr;
error = (*jvmti)->Allocate(jvmti,len,(unsigned char **)&ptr);
check_jvmti_error(jvmti,error,"Cannot allocate memory");
}


JNICALL jint objectCountingCallback(jlong class_tag,jlong size,jlong* tag_ptr,jint length,void* user_data){
    int* count = (int*)user_data;
    *count+=1;
    return JVMTI_VISIT_OBJECTS;
}

JNICALL jint stringPrimitiveValueCallback(jlong class_tag,jlong size,jlong* tag_ptr,const jchar* value,jint value_length,void* user_data){
printf("Inside String primitive call back\n");
printf("%s\n",(char*)value);
return JVMTI_VISIT_OBJECTS;
}


JNICALL jint primitiveFieldCallBack(jvmtiHeapReferenceKind kind,const jvmtiHeapReferenceInfo* info,jlong object_class_tag,jlong* object_tag_ptr,jvalue value,jvmtiPrimitiveType value_type,void *user_data){
printf("Inside Primitive field callback\n");
switch(value_type){
    case 90 : {
                printf("%d\n",value.z);
                break;
    }
    case 66 : {
                printf("%d\n",value.b);
                break;
    }
    case 67 : {
                printf("%c\n",value.c);
                break;
    }
    case 83 : {
                printf("%d\n",value.s);
                break;
    }
    case 73 : {
                printf("%d\n",value.i);
                break;
    }
    case 74 : {
                printf("%ld\n",value.j);
                break;
    }
    case 70 : {
                printf("%f\n",value.f);
                break;
    }
    case 68 : {
                printf("%f\n",value.d);
                break;
    }
}
return JVMTI_VISIT_OBJECTS;
}


JNIEXPORT jint JNICALL Java_Test_countInstances(JNIEnv *env,jclass thisClass,jclass klass){
    int count =0 ;
    jvmtiError error;
    jvmtiHeapCallbacks callbacks;
jvmtiEnv *jvmti;
    (void)memset(&callbacks,0,sizeof(callbacks));
    callbacks.heap_iteration_callback = &objectCountingCallback;
    jvmti = gdata->jvmti;
error = (*jvmti)->IterateThroughHeap(jvmti,0,klass,&callbacks,&count);
//  check_jvmti_error(*gdata->jvmti,error,"Unable to iterate through the heap");
    return count;
}

static void enter_critical_section(jvmtiEnv *jvmti){
jvmtiError error;
error = (*jvmti)->RawMonitorEnter(jvmti,gdata->lock);
check_jvmti_error(jvmti,error,"Cannot enter with raw monitor");
}

static void exit_critical_section(jvmtiEnv *jvmti){
jvmtiError error;
error = (*jvmti)->RawMonitorExit(jvmti,gdata->lock);
check_jvmti_error(jvmti,error,"Cannot exit with raw monitor");
}

static void JNICALL callbackVMInit(jvmtiEnv *jvmti,JNIEnv *env,jthread thread){
jvmtiError error;
//  enter_critical_section(jvmti);{ /* not needed since we are just setting event notifications */
printf("Initializing JVM\n");
error = (*jvmti)->SetEventNotificationMode(jvmti,JVMTI_ENABLE,JVMTI_EVENT_EXCEPTION,(jthread)NULL);
//  error = (*jvmti)->SetEventNotificationMode(jvmti,JVMTI_ENABLE,JVMTI_EVENT_METHOD_ENTRY,(jthread)NULL);
check_jvmti_error(jvmti,error,"Cannot set Exception Event notification");
//  } exit_critical_section(jvmti);
}



static void JNICALL callbackException(jvmtiEnv *jvmti, JNIEnv *env,
    jthread thread, jmethodID method, jlocation location, jobject exception,
    jmethodID catch_method, jlocation catch_location) {
jvmtiFrameInfo frames[10];
jint count, entry_count_ptr;
int i, j;
jvmtiError error;
char *sig, *gsig,*methodName,*className;
jclass declaring_class_ptr;
jvmtiLocalVariableEntry *table_ptr;

error = (*jvmti)->GetStackTrace(jvmti, thread, 0, 10, frames, &count);
if (check_jvmti_error(jvmti, error, "Cannot Get Frame") && count >= 1) {
    for (i = 0; i < count; i++) {
        error = (*jvmti)->GetMethodName(jvmti, frames[i].method,
                &methodName, &sig, &gsig);
        if (check_jvmti_error(jvmti, error, "Cannot Get method name")) {

            error = (*jvmti)->GetMethodDeclaringClass(jvmti,
                    frames[i].method, &declaring_class_ptr);
            check_jvmti_error(jvmti, error,
                    "Cannot Get method declaring class");

            error = (*jvmti)->GetClassSignature(jvmti, declaring_class_ptr,
                    &className, NULL);
            check_jvmti_error(jvmti, error, "Cannot get class signature");

            error = (*jvmti)->GetLocalVariableTable(jvmti, frames[i].method,
                    &entry_count_ptr, &table_ptr);
            check_jvmti_error(jvmti, error,
                    "Cannot Get Local Variable Table");

            if (strstr(className, "java") == NULL
                    && strstr(className, "javax") == NULL   
                    && strstr(className, "sun") == NULL) {
                printf(
                    "Got Exception in  Method: %s at Line: %ld with Signature:%s,%s within Class:%s\n",
                    methodName, frames[i].location, sig, gsig, className);

                for (j = 0; j < entry_count_ptr; j++) {
                    printf("Field Signature:%s\n", table_ptr[j].signature);
                    switch (*(table_ptr[j].signature)) {
                    case 'B': {
                        jint value_ptr;
                        error = (*jvmti)->GetLocalInt(jvmti, thread, i,
                                table_ptr[j].slot, &value_ptr);
                        check_jvmti_error(jvmti, error,
                                "Cannot Get Local Variable Byte");

                        printf("Value of Field %s is %d.\n", table_ptr[j].name, (jbyte)value_ptr);
                        break;
                    }

                    case 'C': {
                        jint value_ptr;
                        error = (*jvmti)->GetLocalInt(jvmti, thread, i,
                                table_ptr[j].slot, &value_ptr);
                        check_jvmti_error(jvmti, error,
                                "Cannot Get Local Variable Char");

                        printf("Value of Field %s is %c.\n", table_ptr[j].name, (jchar)value_ptr);
                        break;
                    }
                    case 'D': {
                        jdouble value_ptr;
                        error = (*jvmti)->GetLocalDouble(jvmti, thread, i,
                                table_ptr[j].slot, &value_ptr);
                        check_jvmti_error(jvmti, error,
                                "Cannot Get Local Variable Double");

                        printf("Value of Field %s is %f.\n", table_ptr[j].name, value_ptr);
                        break;
                    }
                    case 'F': {
                        jfloat value_ptr;
                        error = (*jvmti)->GetLocalFloat(jvmti, thread, i,
                                table_ptr[j].slot, &value_ptr);
                        check_jvmti_error(jvmti, error,
                                "Cannot Get Local Variable Float");

                        printf("Value of Field %s is %f.\n", table_ptr[j].name, value_ptr);
                        break;
                    }
                    case 'I': {
                        jint value_ptr;
                        error = (*jvmti)->GetLocalInt(jvmti, thread, i,
                                table_ptr[j].slot, &value_ptr);
                        check_jvmti_error(jvmti, error,
                                "Cannot Get Local Variable Integer");

                        printf("Value of Field %s is %d.\n", table_ptr[j].name, value_ptr);
                        break;
                    }
                    case 'J': {
                        jlong value_ptr;
                        error = (*jvmti)->GetLocalLong(jvmti, thread, i,
                                table_ptr[j].slot, &value_ptr);
                        check_jvmti_error(jvmti, error,
                                "Cannot Get Local Variable Long");

                        printf("Value of Field %s is %ld.\n", table_ptr[j].name, value_ptr);
                        break;
                    }
                    case 'S':{
                        jint value_ptr;
                        error = (*jvmti)->GetLocalInt(jvmti, thread, i,
                                table_ptr[j].slot, &value_ptr);
                        check_jvmti_error(jvmti, error,
                                "Cannot Get Local Variable Short");

                        printf("Value of Field %s is %d.\n", table_ptr[j].name, (jshort)value_ptr);
                        break;
                    }
                    case 'Z':{
                        jint value_ptr;
                        error = (*jvmti)->GetLocalInt(jvmti, thread, i,
                                table_ptr[j].slot, &value_ptr);
                        check_jvmti_error(jvmti, error,
                                "Cannot Get Local Variable Boolean");

                        printf("Value of Field %s is %d.\n", table_ptr[j].name, (jboolean)value_ptr);
                        break;
                    }
                    case 'L':{
                        int count=0;
                        jobject value_ptr;
                        jclass klaz;
                        jfieldID field;
                        jstring value;
                        const char *stringVal;
                        jvmtiHeapCallbacks callbacks;
                        // (void)memset(&callbacks,0,sizeof(callbacks));
                        // callbacks.primitive_field_callback = &primitiveFieldCallBack;
                        // callbacks.string_primitive_value_callback = &stringPrimitiveValueCallback;
                        // if(strcmp(table_ptr[j].name,"this")==0){
                         // printf("Iterating through primitive fields of this object\n");  
                         error = (*jvmti)->GetLocalObject(jvmti, thread, i,table_ptr[j].slot, &value_ptr);
                         check_jvmti_error(jvmti, error,"Cannot Get Local Variable Object");
                        //  error =    (*jvmti)->IterateThroughHeap(jvmti,0,declaring_class_ptr,&callbacks,&count);
                        //  error = (*jvmti)->FollowReferences(jvmti,0,declaring_class_ptr,value_ptr,&callbacks,&count);
                        // }


                    //  char *klazName;
                    //  error = (*jvmti)->GetLocalObject(jvmti, thread, i,
                    //          table_ptr[j].slot, &value_ptr);
                    //  check_jvmti_error(jvmti, error,
                    //          "Cannot Get Local Variable Object");
                    //  if(!error){
                    //      klaz = (*env)->GetObjectClass(env,value_ptr);
                    //      error = (*jvmti)->GetClassSignature(jvmti, klaz,
                    // &klazName, NULL);
                    //      if(strstr(klazName,"String")!=NULL){
                    //          printf("...%s\n",klazName);
                    //          field = (*env)->GetFieldID(env,declaring_class_ptr,table_ptr[j].name,"S");
                    //          value = (jstring)(*env)->GetObjectField(env,value_ptr,field);
                    //          stringVal = (*env)->GetStringUTFChars(env,value,0);
                    //          printf("Value of Field %s is .\n", stringVal);
                            }
                        }


                        printf("Value of Field %s is .\n", table_ptr[j].name);
                        break;
                    }
                    case '[':{
                        printf("This is an array reference \n");
                        printf("Value of Field %s is .\n", table_ptr[j].name);  
                        break;
                    }
                    default:
                        printf("Can't get %s type.\n",
                                table_ptr[j].signature);
                    }

                }
            }

        }
    }
 }

 }



JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm,char *options,void *reserved){
jvmtiEnv *jvmti;
jvmtiCapabilities capabilities;
jvmtiError error;
jint result;
jvmtiEventCallbacks callbacks;

result = (*jvm)->GetEnv(jvm,(void **)&jvmti,JVMTI_VERSION_1);
if(result!=JNI_OK){
    printf("Unable to access JVMTI! \n");
}
    gdata = (GlobalAgentData*)malloc(sizeof(GlobalAgentData));
    gdata->jvmti=jvmti;

(void)memset(&capabilities,0,sizeof(jvmtiCapabilities));
capabilities.can_tag_objects = 1;
capabilities.can_signal_thread=1;
capabilities.can_get_owned_monitor_info=1;
capabilities.can_generate_method_entry_events=1;
capabilities.can_generate_exception_events=1;
capabilities.can_access_local_variables=1;

error = (*(gdata->jvmti))->AddCapabilities(gdata->jvmti,&capabilities);
check_jvmti_error(gdata->jvmti,error,"Unable to set Capabilities");  

(void)memset(&callbacks,0,sizeof(callbacks));
callbacks.VMInit = &callbackVMInit;
callbacks.Exception = &callbackException;
//callbacks.MethodEntry = &callbackMethodEntry;

error = (*(gdata->jvmti))->SetEventCallbacks(gdata->jvmti,&callbacks,(jint)sizeof(callbacks));
check_jvmti_error(gdata->jvmti,error,"Cannot set event callbacks");

error = (*(gdata->jvmti))->SetEventNotificationMode(gdata->jvmti,JVMTI_ENABLE,JVMTI_EVENT_VM_INIT,(jthread)NULL);
check_jvmti_error(gdata->jvmti,error,"Cannot set event notification");

error = (*(gdata->jvmti))->CreateRawMonitor(gdata->jvmti,"agent data",&(gdata->lock));
check_jvmti_error(gdata->jvmti,error,"Cannot create raw monitor");

printf("A message from my custom super agent!!\n");
return JNI_OK;
} 
void JNICALL tdMethodExit(...)
{
    jvmtiError error;
    //method 
    char * method_name;
    char * method_signature;
    jclass declaring_klass;
    char * klass_signature;
    jint local_count;
    jvmtiLocalVariableEntry * Var_table;
    //locals
    char * local_name;
    char * local_signature;
    char * local_generic_signature;
    jint local_slot;
    jint local_depth;
    jobject  local_object;

    error = (*jvmti_env).GetMethodDeclaringClass(method, &declaring_klass);
    error = (*jvmti_env).GetClassSignature(declaring_klass, &klass_signature, NULL);
    if (strstr(klass_signature, "Ldemo/SimpleThread$1") != NULL) {// 
        error = (*jvmti_env).GetMethodName(method, &method_name, &method_signature, NULL);
        if (strstr(method_name, "run") == NULL) {
            return;
        }
        error = (*jvmti_env).GetLocalVariableTable(method, &local_count, &Var_table);
        //show locals, skip slot 0
        for (int i = 1; i < local_count; i++)
        {
            local_depth = 0;
            jvmtiLocalVariableEntry * temp = Var_table + i;
            local_name = temp->name;
            local_signature = temp->signature;
            local_slot = temp->slot;
            cout << local_name << endl;
            error = (*jvmti_env).GetLocalObject(thread, local_depth, local_slot, &local_object);

            error = (*jvmti_env).Deallocate((unsigned char *)local_name);
            error = (*jvmti_env).Deallocate((unsigned char *)local_signature);
        }
    }
 }