Java 尝试使用jvmti访问异常和线程对象的值时出现无效插槽错误
我有下面的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() {
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);
}
}
}