1 #include <stdio.h>
2 #include <jvmti.h>
3 #include <tijmp.h>
4 #include <find_child_objects.h>
5 #include <tag_list.h>
6 #include <walk_heap.h>
7 #include <tijmp_class_handler.h>
8 
9 extern jvmtiEnv* jvmti;
10 extern jlong current_object_tag;
11 
12 typedef struct {
13     tag_list* tl;
14     tag_list* tijmp_classes;
15 } tlp;
16 
fco(jvmtiHeapReferenceKind reference_kind,const jvmtiHeapReferenceInfo * reference_info,jlong class_tag,jlong referrer_class_tag,jlong size,jlong * tag,jlong * referrer_tag_ptr,jint length,void * user_data)17 static jint JNICALL fco (jvmtiHeapReferenceKind reference_kind,
18 		 const jvmtiHeapReferenceInfo* reference_info,
19 		 jlong class_tag, jlong referrer_class_tag,
20 		 jlong size, jlong* tag, jlong* referrer_tag_ptr,
21 		 jint length, void* user_data) {
22     tlp* p = (tlp*)user_data;
23 
24     /* ignore all odd references... */
25     if (reference_kind != JVMTI_HEAP_REFERENCE_FIELD &&
26 	reference_kind != JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT)
27 	return 0;
28 
29     /* ignore references to and from tijmp classes. */
30     if (is_tijmp_class (referrer_class_tag, p->tijmp_classes))
31 	return 0;
32     if (is_tijmp_class (class_tag, p->tijmp_classes))
33 	return JVMTI_VISIT_OBJECTS;
34 
35     if (*tag == 0)
36 	*tag = current_object_tag--;
37 
38     add_tag (p->tl, *tag);
39     return JVMTI_VISIT_OBJECTS;
40 }
41 
find_all_child_objects(JNIEnv * env,jobject o)42 void JNICALL find_all_child_objects (JNIEnv *env, jobject o) {
43     jvmtiError err;
44     jvmtiHeapCallbacks callbacks;
45     jint count;
46     jobject* objects;
47     jint i;
48     jobjectArray oa;
49     jclass cls;
50     jmethodID m;
51     jint class_count;
52     jclass* cp = NULL;
53     jclass** classes = &cp;
54     tag_list so;
55     tag_list tijmp_classes;
56     tlp p;
57 
58     tag_classes (env, &class_count, classes);
59     (*jvmti)->Deallocate (jvmti, (unsigned char*)classes[0]);
60 
61     setup_tag_list (env, &tijmp_classes, NULL);
62     find_tijmp_classes (env, &tijmp_classes);
63 
64     setup_tag_list (env, &so, NULL);
65     callbacks.heap_iteration_callback = 0;
66     callbacks.heap_reference_callback = fco;
67     callbacks.primitive_field_callback = 0;
68     callbacks.array_primitive_value_callback = 0;
69     callbacks.string_primitive_value_callback = 0;
70     (*jvmti)->SetTag (jvmti, o, -1);
71 
72     p.tl = &so;
73     p.tijmp_classes = &tijmp_classes;
74     err = (*jvmti)->FollowReferences (jvmti, 0, NULL, o, &callbacks, &p);
75     if (err != JVMTI_ERROR_NONE)
76 	handle_global_error (err);
77 
78     cls = (*env)->FindClass (env, "java/lang/Object");
79     (*jvmti)->GetObjectsWithTags (jvmti, so.next_pos, so.tags, &count, &objects, NULL);
80     oa = (*env)->NewObjectArray (env, count, cls, NULL);
81     for (i = 0; i < count; i++)
82 	(*env)->SetObjectArrayElement (env, oa, i, objects[i]);
83     cleanup_tag_list (&so);
84     cleanup_tag_list (&tijmp_classes);
85 
86     cls = (*env)->FindClass (env, "tijmp/TIJMPController");
87     m = (*env)->GetStaticMethodID (env, cls, "childObjects",
88 				   "([Ljava/lang/Object;)V");
89     if (m != NULL)
90 	(*env)->CallStaticVoidMethod (env, cls, m, oa);
91 }
92