Skip to content

Commit

Permalink
watch fields
Browse files Browse the repository at this point in the history
  • Loading branch information
jbalint committed Mar 11, 2017
1 parent d8ae08b commit e06df27
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 3 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ LJ_OBJS = lua_java.o lua_jvmti_event.o \
lua_java/lj_method.o \
lua_java/lj_raw_monitor.o \
lua_java/lj_stack_frame.o \
lua_java/lj_watch.o \
java_bridge/types.o

libyt.so: yt.o lua_interface.o jni_util.o $(LJ_OBJS)
Expand Down
2 changes: 2 additions & 0 deletions lua_java.c
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,7 @@ void lj_force_early_return_register(lua_State *L);
void lj_method_register(lua_State *L);
void lj_raw_monitor_register(lua_State *L);
void lj_stack_frame_register(lua_State *L);
void lj_watch_register(lua_State *L);

void lj_init(lua_State *L, JavaVM *jvm, jvmtiEnv *jvmti)
{
Expand All @@ -850,6 +851,7 @@ void lj_init(lua_State *L, JavaVM *jvm, jvmtiEnv *jvmti)
lj_method_register(L);
lj_raw_monitor_register(L);
lj_stack_frame_register(L);
lj_watch_register(L);

lua_register(L, "lj_set_breakpoint", lj_set_breakpoint);
lua_register(L, "lj_clear_breakpoint", lj_clear_breakpoint);
Expand Down
4 changes: 1 addition & 3 deletions lua_java/lj_class.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ static int lj_get_loaded_classes(lua_State *L)
incremented for the next iteration. We need to tag all items and
then retrieve them. There is no reason/method to clear all tags so
we increment the number so it's different next time. It's
*possible* that if you used this method a (max jlong) times that
*possible* that if you used this method (max jlong) times that
there may be objects leftover with an old tag.
*/
static jlong class_instances_search_tag = 1000;
Expand Down Expand Up @@ -186,8 +186,6 @@ static int lj_get_class_instances(lua_State *L) {
lj_err = (*current_jvmti())->GetObjectsWithTags(current_jvmti(), 1, &class_instances_search_tag, &output_count, &obj_output, &tag_output);
lj_check_jvmti_error(L);

fprintf(stderr, "output_count=%d\n", output_count);

/* add it to the result */
lua_createtable(L, output_count, 0);
for (i = 0; i < output_count; ++i) {
Expand Down
40 changes: 40 additions & 0 deletions lua_java/lj_watch.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "myjni.h"
#include "jni_util.h"
#include "lua_interface.h"
#include "lua_java.h"
#include "java_bridge.h"
#include "lj_internal.h"

static int lj_set_field_access_watch(lua_State *L)
{
lj_field_id *field_id;

field_id = (lj_field_id *)luaL_checkudata(L, 1, "jfield_id");
lua_pop(L, 1);

lj_err = (*current_jvmti())->SetFieldAccessWatch(current_jvmti(), field_id->class, field_id->field_id);
lj_check_jvmti_error(L);

return 0;
}

static int lj_set_field_modification_watch(lua_State *L)
{
lj_field_id *field_id;

field_id = (lj_field_id *)luaL_checkudata(L, 1, "jfield_id");
lua_pop(L, 1);

lj_err = (*current_jvmti())->SetFieldModificationWatch(current_jvmti(), field_id->class, field_id->field_id);
lj_check_jvmti_error(L);

return 0;
}

void lj_watch_register(lua_State *L)
{
lua_register(L, "lj_set_field_access_watch", lj_set_field_access_watch);
/* lua_register(L, "lj_clear_field_access_watch", lj_clear_field_access_watch); */
lua_register(L, "lj_set_field_modification_watch", lj_set_field_modification_watch);
/* lua_register(L, "lj_clear_field_modification_watch", lj_clear_field_modification_watch); */
}
101 changes: 101 additions & 0 deletions lua_jvmti_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ static struct {
int cb_single_step_ref;
int cb_exception_throw_ref;
int cb_exception_catch_ref;
int cb_field_access_ref;
int cb_field_modification_ref;
} lj_jvmti_callbacks;

void lj_init_jvmti_event()
Expand All @@ -38,6 +40,9 @@ void lj_init_jvmti_event()

lj_jvmti_callbacks.cb_exception_throw_ref = LUA_NOREF;
lj_jvmti_callbacks.cb_exception_catch_ref = LUA_NOREF;

lj_jvmti_callbacks.cb_field_access_ref = LUA_NOREF;
lj_jvmti_callbacks.cb_field_modification_ref = LUA_NOREF;
}

static void disable_events_before_callback_handling(lua_State *L)
Expand Down Expand Up @@ -204,6 +209,82 @@ static void JNICALL cb_exception_throw(jvmtiEnv *jvmti, JNIEnv *jni, jthread thr
enable_events_after_callback_handling(lj_L);
}

static void JNICALL cb_field_access(jvmtiEnv *jvmti,
JNIEnv* jni,
jthread thread,
jmethodID method_id,
jlocation location,
jclass field_klass,
jobject object,
jfieldID field_id)
{
int ref = lj_jvmti_callbacks.cb_field_access_ref;
lua_State *L;

printf("***** cb_field_access_ref *****\n");
if (ref == LUA_NOREF)
return;

L = lua_newthread(lj_L);

lj_current_thread = (*jni)->NewGlobalRef(jni, thread);
assert(lj_current_thread);

disable_events_before_callback_handling(lj_L);

lua_pushcfunction(L, lua_print_traceback);
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
new_jobject(L, thread);
new_jmethod_id(L, method_id);
lua_pushinteger(L, location);
new_jobject(L, field_klass);
new_jobject(L, object);
new_jfield_id(L, field_id, field_klass);
lua_pcall(L, 6, 0, -8);
lua_pop(lj_L, 1); /* the new lua_State, we're done with it */

enable_events_after_callback_handling(lj_L);
}

static void JNICALL cb_field_modification(jvmtiEnv *jvmti,
JNIEnv* jni,
jthread thread,
jmethodID method_id,
jlocation location,
jclass field_klass,
jobject object,
jfieldID field_id,
char signature_type,
jvalue new_value)
{
int ref = lj_jvmti_callbacks.cb_field_modification_ref;
lua_State *L;

printf("***** cb_field_modification_ref *****\n");
if (ref == LUA_NOREF)
return;

L = lua_newthread(lj_L);

lj_current_thread = (*jni)->NewGlobalRef(jni, thread);
assert(lj_current_thread);

disable_events_before_callback_handling(lj_L);

lua_pushcfunction(L, lua_print_traceback);
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
new_jobject(L, thread);
new_jmethod_id(L, method_id);
lua_pushinteger(L, location);
new_jobject(L, field_klass);
new_jobject(L, object);
new_jfield_id(L, field_id, field_klass);
lua_pcall(L, 6, 0, -8);
lua_pop(lj_L, 1); /* the new lua_State, we're done with it */

enable_events_after_callback_handling(lj_L);
}

static void get_jvmti_callback_pointers(const char *callback,
void ***jvmti_function_ptr_ptr,
void **lj_function_ptr,
Expand Down Expand Up @@ -255,6 +336,18 @@ static void get_jvmti_callback_pointers(const char *callback,
*lj_function_ptr = cb_exception_throw;
*ref_ptr = &lj_jvmti_callbacks.cb_exception_throw_ref;
}
else if (!strcmp(callback, "field_access"))
{
*jvmti_function_ptr_ptr = (void **)&evCbs->FieldAccess;
*lj_function_ptr = cb_field_access;
*ref_ptr = &lj_jvmti_callbacks.cb_field_access_ref;
}
else if (!strcmp(callback, "field_modification"))
{
*jvmti_function_ptr_ptr = (void **)&evCbs->FieldModification;
*lj_function_ptr = cb_field_modification;
*ref_ptr = &lj_jvmti_callbacks.cb_field_modification_ref;
}
}

int lj_set_jvmti_callback(lua_State *L)
Expand Down Expand Up @@ -286,6 +379,10 @@ int lj_set_jvmti_callback(lua_State *L)
lj_err = EV_ENABLET(METHOD_EXIT, get_current_java_thread());
else if (!strcmp(callback, "exception_throw"))
lj_err = EV_ENABLET(EXCEPTION, get_current_java_thread());
else if (!strcmp(callback, "field_access"))
lj_err = EV_ENABLET(FIELD_ACCESS, get_current_java_thread());
else if (!strcmp(callback, "field_modification"))
lj_err = EV_ENABLET(FIELD_MODIFICATION, get_current_java_thread());
lj_check_jvmti_error(L);

get_jvmti_callback_pointers(callback, &jvmti_callback_ptr, &lj_callback_ptr, &ref_ptr);
Expand Down Expand Up @@ -320,6 +417,10 @@ int lj_clear_jvmti_callback(lua_State *L)
EV_DISABLET(METHOD_EXIT, get_current_java_thread());
else if (!strcmp(callback, "exception_throw"))
EV_DISABLET(EXCEPTION, get_current_java_thread());
else if (!strcmp(callback, "field_access"))
EV_DISABLET(FIELD_ACCESS, get_current_java_thread());
else if (!strcmp(callback, "field_modification"))
EV_DISABLET(FIELD_MODIFICATION, get_current_java_thread());
lj_check_jvmti_error(L);

get_jvmti_callback_pointers(callback, &jvmti_callback_ptr, NULL, &ref_ptr);
Expand Down
2 changes: 2 additions & 0 deletions yt.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ Agent_OnLoad(JavaVM *jvm, char *options, void *reserved)
caps.can_generate_single_step_events = 1; /* Used for line-oriented stepping */
/* caps.can_generate_frame_pop_events = 1; */
caps.can_force_early_return = 1;
caps.can_generate_field_access_events = 1;
caps.can_generate_field_modification_events = 1;

rc = (*jvm)->GetEnv(jvm, (void **)&jvmti, JVMTI_VERSION_1_0);
if(rc < 0)
Expand Down

0 comments on commit e06df27

Please sign in to comment.