2017-02-22 4 views
0

を使用したオブジェクトのスレッドしようとすると私は例外がJVMTI、無効なスロットのエラー例外の値にアクセスし、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(); 
    } 
} 
を使用して発生したときにメソッド内の変数の状態を捕獲しようとしていた使用して、次のJavaプログラムを持っています

私が使用していますJVMTIエージェントは、変数の名前にアクセスすることが可能であるが、それは

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)' 

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

答えて

0

私が使用していますJVMTIエージェントは、変数の名前にアクセスすることが可能であるが、それは使用して値を取得しようとすると....

あなたはネイティブコードを投稿しないので、なぜこの問題に遭遇するのかわかりません。私はあなたに別の解決策を与えることができます。 MethodEixtイベントを取得し、の値をで取得します。メソッド終了イベントコールバック関数

以下のようにコールバック関数の擬似コード:

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

"Ldemo/SimpleThread $ 1"、Runnableインタフェースを実装匿名の内部クラスです。大まかなワークフローでは、ターゲットクラスをメソッドに配置し、このメソッドではeの値を取得します。

+0

私はエージェントコードを添付していますので、見てください。 – kumarD

関連する問題