variable una tipos tipo parametros metodos linea guardar ejemplos declarar declara constantes con como cadena java jni jvmti

una - tipos de variables en java ejemplos



Cómo obtener los valores del método de variables locales y variables de clase utilizando jvmti (1)

Estoy tratando de capturar los valores variables usando JVMTI, cuando se genera un evento de excepción, revisé la documentación jvmti y encontré que no hay funciones que me permitan recuperar los valores de los campos (variables), ¿cómo se puede lograr esto?

A continuación se muestra el código del agente:

#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; (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; } 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 callbackMethodEntry(jvmtiEnv *jvmti,JNIEnv *env,jthread thread,jmethodID method){ jvmtiError error; jvmtiLocalVariableEntry **table_ptr; jint count,entry_count_ptr; jobject value_ptr; int j; error = (*jvmti)->GetLocalVariableTable(jvmti,method,&entry_count_ptr,table_ptr); if(check_jvmti_error(jvmti,error,"Cannot Get Local Variable table/n")){ printf("local variable table entry size : %d %s/n",entry_count_ptr,(*table_ptr)[0].name); } // for(j=0;j<*entry_count_ptr;j++){ // error = (*jvmti)->GetLocalObject(jvmti,thread,0,(*table_ptr)[j].slot,&value_ptr); // printf("Field Name:%s/n",(*table_ptr)[j].name); // } } 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; jobject* value_ptr; char *name,*sig,*gsig; 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){ char *methodName,*className; 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"); // 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++){ callbackMethodEntry(jvmti,env,thread,frames[j].method); error = (*jvmti)->GetLocalObject(jvmti,thread,i,table_ptr[j].slot,value_ptr);// change the value of the slot parameter printf("Field Name:%s/n",table_ptr[j].name); } } } } /* error = (*jvmti)->GetMethodName(jvmti,method,&name,&sig,&gsig); check_jvmti_error(jvmti,error,"Cannot Get Method name"); printf("Exception in Method: %s%s at line number: %ld/n",name,sig,location);*/ } 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_tag_objects=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; }

Debajo está el resultado:

ERROR: JVMTI: 101(JVMTI_ERROR_ABSENT_INFORMATION): Cannot Get Local Variable table # # A fatal error has been detected by the Java Runtime Environment: # # SIGSEGV (0xb) at pc=0x00007f3faab0cefa, pid=14869, tid=0x00007f3fad251700 # # JRE version: Java(TM) SE Runtime Environment (8.0_111-b14) (build 1.8.0_111-b14) # Java VM: Java HotSpot(TM) 64-Bit Server VM (25.111-b14 mixed mode linux-amd64 compressed oops) # Problematic frame: # C [liblearnAgent.so+0xefa] callbackException+0x277 # # Core dump written. Default location: /home/kumard/Desktop/core or core.14869 # # An error report file with more information is saved as: # /home/kumard/Desktop/hs_err_pid14869.log # # If you would like to submit a bug report, please visit: # http://bugreport.java.com/bugreport/crash.jsp # The crash happened outside the Java Virtual Machine in native code. # See problematic frame for where to report the bug. # [1] 14869 abort (core dumped) java -agentlib:learnAgent SimpleThread


Esta no es la respuesta completa, pero sí resuelve algunos de los problemas en su agente e imprime los valores para los tipos de datos básicos cuando se produce una excepción. Hemos resuelto problemas en el chat de comentarios. Así que simplemente estoy publicando el código aquí. Cualquier persona interesada en saber más sobre esto puede ver el chat. También puedes dar tu opinión sobre el problema.

#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; (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 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; 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) { char *methodName, *className; 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"); printf( "Got Exception in Method: %s at Line: %ld with Signature:%s,%s within Class:%s/n", methodName, frames[i].location, sig, gsig, className); if (strstr(className, "java") == NULL && strstr(className, "javax") == NULL && strstr(className, "sun") == NULL) { for (j = 0; j < entry_count_ptr; j++) { 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'':{ jobject value_ptr; error = (*jvmti)->GetLocalObject(jvmti, thread, i, table_ptr[j].slot, &value_ptr); check_jvmti_error(jvmti, error, "Cannot Get Local Variable Object"); printf("Value of Field %s is ./n", table_ptr[j].name); break; } default: printf("Can''t get %s type./n", table_ptr[j].signature); } printf("Field Signature:%s/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_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"); error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_EXCEPTION, (jthread) NULL); check_jvmti_error(jvmti, error, "Cannot set Exception Event notification"); (void) memset(&callbacks, 0, sizeof(callbacks)); callbacks.Exception = &callbackException; error = (*(gdata->jvmti))->SetEventCallbacks(gdata->jvmti, &callbacks, (jint) sizeof(callbacks)); check_jvmti_error(gdata->jvmti, error, "Cannot set event callbacks"); 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; }