当前位置: 首页 > 知识库问答 >
问题:

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

越欣怡
2023-03-14
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();
    }
}
 jobject object_value;
 error = jvmti.GetLocalObject(thread, depth, slot, &object_value);
Trying to fetch value of e
JNIException (java/lang/AssertionError): 'Unable to get local value; JVMTI      ERROR: '35' (JVMTI_ERROR_INVALID_SLOT)' 

代理代码如下:

#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;
} 

共有1个答案

越胤
2023-03-14

我正在使用的jvmti代理能够访问变量的名称,但当它试图使用....

您没有发布您的本机代码,所以我不知道为什么您会遇到这种麻烦。我可以给你一个替代方案。注册MethodEixt事件并在MethodExit事件回调函数处获取e的值。

回调函数伪代码如下:

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);
        }
    }
 }
 类似资料:
  • 从终端执行jar时,我得到以下信息: 我搜索了他的错误,发现了一些相同的执行输出错误,但没有解决我的情况。 下面详细介绍了文件的位置、清单内容、所采取的终端步骤以及所涉及的两个类文件的代码内容。 文件位置 > SWT库 舱单 班级 普通人。jar(参见下面的创建): Manifest.txt内容: 终端动作 > 目录更改 . jar创建 舱单检查 普通人。jar执行 密码 用户nterface.c

  • 我在Oracle中有下面的SQL语句,这让我有些头疼。如果Oracle表中的值为null,我尝试返回一个空几何体,但是它失败了,出现以下错误: 错误 ** ORA-29532:Java调用被unpper终止Java异常:java.lang.NullPointerExcema ORA-06512: at"MDSYS.SDO_UTIL",第2421行ORA-06512: at"MDSYS.SDO_UT

  • 我有h2数据库的工作应用程序。db没有连接问题,因为我可以从那里获得一些值,但是当我尝试创建EntityManagerFactory时:然后我在日志中看到: 只有在尝试创建上面提到的时才会出现问题。当我不尝试它时,我可以去h2 web控制台,看到flyway正确地创建了db,进行了插入,并且我可以进行选择/插入等等。 @编辑添加pom.xml

  • 我对php和mySQL是完全陌生的,并且正在尝试连接到远程数据库。这是我的代码:- $result=mysql_query(“Select*FROM Constants”); while($ROW=mysql_fetch_array($result)){echo$ROW['name']; echo“ ”;} mysql_close($con); 对这个问题有什么想法吗?马特·蒂亚

  • 我实际上正在使用GAE构建一个聊天室,问题是我将clientid和令牌存储在chatrromservlet中,并使用datastore密钥访问它们,但当我试图使用该密钥从sayservlet访问数据存储时,我得到一个异常,即没有找到具有该密钥的实体。 我的chatroomservlet say servlet是 如果在访问时有任何错误,请帮助我。

  • 我带着一个我无法解决的问题来到这里。 我在版本1.7中有一个prestashop,我已经移动到另一台服务器,值得一提的是,在旧服务器中,prestashop运行良好。 当我将prestashop迁移到新服务器时,除了我想进入后台,当我想进入后台时,只需将页面留空,其他一切都可以正常工作。 我已经激活了调试模式,但它没有给我任何与后台相关的错误,有趣的是,当调试模式被激活时,我可以毫无问题地进入后台