44
45 #endif
46
47 #define TRUE 1
48 #define FALSE 0
49 #define PRINT_OUT 1
50 #define MAX_TRACES 400
51
52 static jvmtiEnv *jvmti = NULL;
53 static jvmtiEnv *second_jvmti = NULL;
54
55 typedef struct _ObjectTrace{
56 jweak object;
57 size_t size;
58 jvmtiFrameInfo* frames;
59 size_t frame_count;
60 jthread thread;
61 } ObjectTrace;
62
63 typedef struct _EventStorage {
64 int live_object_size;
65 int live_object_count;
66 ObjectTrace** live_objects;
67
68 int garbage_history_size;
69 int garbage_history_index;
70 ObjectTrace** garbage_collected_objects;
71
72 // Two separate mutexes to separate storage data race and the compaction field
73 // data race.
74 pthread_mutex_t storage_mutex;
75
76 int compaction_required;
77 pthread_mutex_t compaction_mutex;
78 } EventStorage;
79
80 typedef struct _ExpectedContentFrame {
81 const char *name;
82 const char *signature;
83 const char *file_name;
126 }
127
128 static jboolean check_sample_content(JNIEnv *env,
129 ObjectTrace* trace,
130 ExpectedContentFrame *expected,
131 size_t expected_count,
132 int print_out_comparisons) {
133 if (expected_count > trace->frame_count) {
134 return FALSE;
135 }
136
137 jvmtiFrameInfo* frames = trace->frames;
138
139 size_t i;
140 for (i = 0; i < expected_count; i++) {
141 // Get basic information out of the trace.
142 int bci = frames[i].location;
143 jmethodID methodid = frames[i].method;
144 char *name = NULL, *signature = NULL, *file_name = NULL;
145
146 if (bci < 0) {
147 return FALSE;
148 }
149
150 // Transform into usable information.
151 int line_number = get_line_number(jvmti, methodid, bci);
152 (*jvmti)->GetMethodName(jvmti, methodid, &name, &signature, 0);
153
154 jclass declaring_class;
155 if (JVMTI_ERROR_NONE !=
156 (*jvmti)->GetMethodDeclaringClass(jvmti, methodid, &declaring_class)) {
157 return FALSE;
158 }
159
160 jvmtiError err = (*jvmti)->GetSourceFileName(jvmti, declaring_class,
161 &file_name);
162 if (err != JVMTI_ERROR_NONE) {
163 return FALSE;
164 }
165
166 // Compare now, none should be NULL.
220 string_id = (*env)->GetFieldID(env, frame_class, "fileName",
221 "Ljava/lang/String;");
222 string_object = (jstring) (*env)->GetObjectField(env, obj, string_id);
223 const char* file_name = (*env)->GetStringUTFChars(env, string_object, 0);
224
225 string_id = (*env)->GetFieldID(env, frame_class, "signature",
226 "Ljava/lang/String;");
227 string_object = (jstring) (*env)->GetObjectField(env, obj, string_id);
228 const char* signature= (*env)->GetStringUTFChars(env, string_object, 0);
229
230 native_frames[i].name = method;
231 native_frames[i].file_name = file_name;
232 native_frames[i].signature = signature;
233 native_frames[i].line_number = line_number;
234 }
235 }
236
237 // Internal storage system implementation.
238
239 static EventStorage global_event_storage;
240
241 static void event_storage_set_compaction_required(EventStorage* storage) {
242 pthread_mutex_lock(&storage->compaction_mutex);
243 storage->compaction_required = 1;
244 pthread_mutex_unlock(&storage->compaction_mutex);
245 }
246
247 static int event_storage_get_compaction_required(EventStorage* storage) {
248 pthread_mutex_lock(&storage->compaction_mutex);
249 int result = storage->compaction_required;
250 pthread_mutex_unlock(&storage->compaction_mutex);
251 return result;
252 }
253
254 static void event_storage_set_garbage_history(EventStorage* storage, int value) {
255 pthread_mutex_lock(&storage->storage_mutex);
256 global_event_storage.garbage_history_size = value;
257 free(global_event_storage.garbage_collected_objects);
258 size_t size =
259 sizeof(*global_event_storage.garbage_collected_objects) * value;
356 jlong size) {
357 jvmtiFrameInfo frames[64];
358 jint count;
359 jvmtiError err;
360
361 err = (*jvmti)->GetStackTrace(jvmti, thread, 0, 64, frames, &count);
362 if (err == JVMTI_ERROR_NONE && count >= 1) {
363 jvmtiFrameInfo* allocated_frames = (jvmtiFrameInfo*) malloc(count * sizeof(*allocated_frames));
364 memcpy(allocated_frames, frames, count * sizeof(*allocated_frames));
365
366 ObjectTrace* live_object = (ObjectTrace*) malloc(sizeof(*live_object));
367 live_object->frames = allocated_frames;
368 live_object->frame_count = count;
369 live_object->size = size;
370 live_object->thread = thread;
371 live_object->object = (*jni)->NewWeakGlobalRef(jni, object);
372
373 // Only now lock and get things done quickly.
374 pthread_mutex_lock(&storage->storage_mutex);
375
376 if (storage->live_object_count >= storage->live_object_size) {
377 event_storage_augment_storage(storage);
378 }
379 assert(storage->live_object_count < storage->live_object_size);
380
381 storage->live_objects[storage->live_object_count] = live_object;
382 storage->live_object_count++;
383
384 pthread_mutex_unlock(&storage->storage_mutex);
385 }
386 }
387
388 static void event_storage_compact(EventStorage* storage, JNIEnv* jni) {
389 pthread_mutex_lock(&storage->compaction_mutex);
390 storage->compaction_required = 0;
391 pthread_mutex_unlock(&storage->compaction_mutex);
392
393 pthread_mutex_lock(&storage->storage_mutex);
394
395 int max = storage->live_object_count;
410 }
411 }
412
413 storage->live_object_count = dest;
414 pthread_mutex_unlock(&storage->storage_mutex);
415 }
416
417 static void event_storage_free_objects(ObjectTrace** array, int max) {
418 int i;
419 for (i = 0; i < max; i++) {
420 free(array[i]), array[i] = NULL;
421 }
422 }
423
424 static void event_storage_reset(EventStorage* storage) {
425 pthread_mutex_lock(&storage->storage_mutex);
426
427 // Reset everything except the mutex and the garbage collection.
428 event_storage_free_objects(storage->live_objects,
429 storage->live_object_count);
430 storage->live_object_size = 0;
431 storage->live_object_count = 0;
432 free(storage->live_objects), storage->live_objects = NULL;
433
434 event_storage_free_objects(storage->garbage_collected_objects,
435 storage->garbage_history_size);
436
437 storage->compaction_required = 0;
438 storage->garbage_history_index = 0;
439
440 pthread_mutex_unlock(&storage->storage_mutex);
441 }
442
443 // Start of the JVMTI agent code.
444
445 static const char *EXC_CNAME = "java/lang/Exception";
446
447 static int check_error(jvmtiError err, const char *s) {
448 if (err != JVMTI_ERROR_NONE) {
449 printf(" ## %s error: %d\n", s, err);
450 return 1;
451 }
452 return 0;
453 }
454
455 static int check_capability_error(jvmtiError err, const char *s) {
456 if (err != JVMTI_ERROR_NONE) {
457 if (err == JVMTI_ERROR_MUST_POSSESS_CAPABILITY) {
458 return 0;
459 }
460 printf(" ## %s error: %d\n", s, err);
461 return 1;
462 }
491 return JNI_VERSION_1_8;
492 }
493
494 JNIEXPORT
495 void JNICALL SampledObjectAlloc(jvmtiEnv *jvmti_env,
496 JNIEnv* jni_env,
497 jthread thread,
498 jobject object,
499 jclass object_klass,
500 jlong size) {
501 if (event_storage_get_compaction_required(&global_event_storage)) {
502 event_storage_compact(&global_event_storage, jni_env);
503 }
504
505 jvmtiThreadInfo first_info;
506 event_storage_add(&global_event_storage, jni_env, thread, object,
507 object_klass, size);
508 }
509
510 JNIEXPORT
511 void JNICALL GarbageCollectionFinish(jvmtiEnv *jvmti_env) {
512 event_storage_set_compaction_required(&global_event_storage);
513 }
514
515 static int enable_notifications() {
516 if (check_error((*jvmti)->SetEventNotificationMode(
517 jvmti, JVMTI_ENABLE, JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, NULL),
518 "Set event notifications")) {
519 return 1;
520 }
521
522 return check_error((*jvmti)->SetEventNotificationMode(
523 jvmti, JVMTI_ENABLE, JVMTI_EVENT_SAMPLED_OBJECT_ALLOC, NULL),
524 "Set event notifications");
525 }
526
527 static int enable_notifications_for_two_threads(jthread first, jthread second) {
528 if (check_error((*jvmti)->SetEventNotificationMode(
529 jvmti, JVMTI_ENABLE, JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, NULL),
530 "Set event notifications")) {
553
554 res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
555 JVMTI_VERSION_9);
556 if (res != JNI_OK || jvmti == NULL) {
557 fprintf(stderr, "Error: wrong result of a valid call to GetEnv!\n");
558 return JNI_ERR;
559 }
560
561 // Get second jvmti environment.
562 res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &second_jvmti),
563 JVMTI_VERSION_9);
564 if (res != JNI_OK || second_jvmti == NULL) {
565 fprintf(stderr, "Error: wrong result of a valid second call to GetEnv!\n");
566 return JNI_ERR;
567 }
568
569 pthread_mutex_init(&global_event_storage.storage_mutex, 0);
570 pthread_mutex_init(&global_event_storage.compaction_mutex, 0);
571 event_storage_set_garbage_history(&global_event_storage, 200);
572
573 jvmtiEventCallbacks callbacks;
574 memset(&callbacks, 0, sizeof(callbacks));
575 callbacks.SampledObjectAlloc = &SampledObjectAlloc;
576 callbacks.GarbageCollectionFinish = &GarbageCollectionFinish;
577
578 jvmtiCapabilities caps;
579 memset(&caps, 0, sizeof(caps));
580 // Get line numbers, sample events, filename, and gc events for the tests.
581 caps.can_get_line_numbers = 1;
582 caps.can_generate_sampled_alloc_events = 1;
583 caps.can_get_source_file_name = 1;
584 caps.can_generate_garbage_collection_events = 1;
585 if (check_error((*jvmti)->AddCapabilities(jvmti, &caps), "Add capabilities")) {
586 return JNI_ERR;
587 }
588
589 if (check_error((*jvmti)->SetEventCallbacks(jvmti, &callbacks,
590 sizeof(jvmtiEventCallbacks)),
591 " Set Event Callbacks")) {
592 return JNI_ERR;
593 }
594 return JNI_OK;
595 }
596
597 JNIEXPORT void JNICALL
598 Java_MyPackage_HeapMonitor_setSamplingRate(JNIEnv* env, jclass cls, jint value) {
599 (*jvmti)->SetHeapSamplingRate(jvmti, value);
600 }
601
602 JNIEXPORT jboolean JNICALL
640 fill_native_frames(env, frames, native_frames, size);
641 return event_storage_contains(env, &global_event_storage, native_frames, size);
642 }
643
644 JNIEXPORT jboolean JNICALL
645 Java_MyPackage_HeapMonitor_garbageContains(JNIEnv* env, jclass cls, jobjectArray frames) {
646 jsize size = (*env)->GetArrayLength(env, frames);
647 ExpectedContentFrame native_frames[size];
648 fill_native_frames(env, frames, native_frames, size);
649 return event_storage_garbage_contains(env, &global_event_storage, native_frames, size);
650 }
651
652 JNIEXPORT void JNICALL
653 Java_MyPackage_HeapMonitor_forceGarbageCollection(JNIEnv* env, jclass cls) {
654 check_error((*jvmti)->ForceGarbageCollection(jvmti),
655 "Forced Garbage Collection");
656 }
657
658 JNIEXPORT void JNICALL
659 Java_MyPackage_HeapMonitor_resetEventStorage(JNIEnv* env, jclass cls) {
660 return event_storage_reset(&global_event_storage);
661 }
662
663 JNIEXPORT jboolean JNICALL
664 Java_MyPackage_HeapMonitorNoCapabilityTest_allSamplingMethodsFail(JNIEnv *env,
665 jclass cls) {
666 jvmtiCapabilities caps;
667 memset(&caps, 0, sizeof(caps));
668 caps.can_generate_sampled_alloc_events = 1;
669 if (check_error((*jvmti)->RelinquishCapabilities(jvmti, &caps),
670 "Add capabilities\n")){
671 return FALSE;
672 }
673
674 if (check_capability_error((*jvmti)->SetHeapSamplingRate(jvmti, 1<<19),
675 "Set Heap Sampling Rate")) {
676 return FALSE;
677 }
678 return TRUE;
679 }
680
797 Java_MyPackage_HeapMonitorEventsForTwoThreadsTest_checkSamples(JNIEnv* env,
798 jclass cls) {
799 pthread_mutex_lock(&global_event_storage.storage_mutex);
800 jint trace_counter;
801
802 const int expected_num_threads = 2;
803 ThreadsFound thread_data;
804 thread_data.num_threads = 0;
805 thread_data.threads = malloc(sizeof(jthread) * expected_num_threads);
806 memset(thread_data.threads, 0, sizeof(jthread) * expected_num_threads);
807
808 find_threads_in_array(&thread_data, global_event_storage.live_objects,
809 global_event_storage.live_object_count);
810
811 pthread_mutex_unlock(&global_event_storage.storage_mutex);
812
813 int obtained_threads = thread_data.num_threads;
814 return obtained_threads == expected_num_threads;
815 }
816
817 static EventStorage second_global_event_storage;
818
819 JNIEXPORT
820 void JNICALL SampledObjectAlloc2(jvmtiEnv *jvmti_env,
821 JNIEnv* jni_env,
822 jthread thread,
823 jobject object,
824 jclass object_klass,
825 jlong size) {
826 event_storage_add(&second_global_event_storage, jni_env, thread, object,
827 object_klass, size);
828 }
829
830 JNIEXPORT jboolean JNICALL
831 Java_MyPackage_HeapMonitorTwoAgentsTest_enablingSamplingInSecondaryAgent(
832 JNIEnv* env, jclass cls) {
833 pthread_mutex_init(&second_global_event_storage.storage_mutex, 0);
834 pthread_mutex_init(&second_global_event_storage.compaction_mutex, 0);
835 event_storage_set_garbage_history(&second_global_event_storage, 200);
836
837 jvmtiCapabilities caps;
838 memset(&caps, 0, sizeof(caps));
839 caps.can_generate_sampled_alloc_events = 1;
840 if (check_error((*second_jvmti)->AddCapabilities(second_jvmti, &caps),
841 "Set the capability for second agent")) {
842 return FALSE;
843 }
844
845 jvmtiEventCallbacks callbacks;
846 memset(&callbacks, 0, sizeof(callbacks));
847 callbacks.SampledObjectAlloc = &SampledObjectAlloc2;
848
849 if (check_error((*second_jvmti)->SetEventCallbacks(second_jvmti, &callbacks,
850 sizeof(jvmtiEventCallbacks)),
851 " Set Event Callbacks for second agent")) {
852 return FALSE;
853 }
854
855 return TRUE;
856 }
857
858 JNIEXPORT jboolean JNICALL
859 Java_MyPackage_HeapMonitorTwoAgentsTest_obtainedEventsForBothAgents(
860 JNIEnv* env, jclass cls, jobjectArray frames) {
861 jsize size = (*env)->GetArrayLength(env, frames);
862 ExpectedContentFrame native_frames[size];
863 fill_native_frames(env, frames, native_frames, size);
864
865 int first_storage_contained_events =
866 event_storage_contains(env, &global_event_storage, native_frames, size);
867
868 int second_storage_contained_events =
869 event_storage_contains(env, &second_global_event_storage, native_frames, size);
870
871 return first_storage_contained_events && second_storage_contained_events;
872 }
873
874 #ifdef __cplusplus
875 }
876 #endif
|
44
45 #endif
46
47 #define TRUE 1
48 #define FALSE 0
49 #define PRINT_OUT 1
50 #define MAX_TRACES 400
51
52 static jvmtiEnv *jvmti = NULL;
53 static jvmtiEnv *second_jvmti = NULL;
54
55 typedef struct _ObjectTrace{
56 jweak object;
57 size_t size;
58 jvmtiFrameInfo* frames;
59 size_t frame_count;
60 jthread thread;
61 } ObjectTrace;
62
63 typedef struct _EventStorage {
64 int live_object_additions;
65 int live_object_size;
66 int live_object_count;
67 ObjectTrace** live_objects;
68
69 int garbage_history_size;
70 int garbage_history_index;
71 ObjectTrace** garbage_collected_objects;
72
73 // Two separate mutexes to separate storage data race and the compaction field
74 // data race.
75 pthread_mutex_t storage_mutex;
76
77 int compaction_required;
78 pthread_mutex_t compaction_mutex;
79 } EventStorage;
80
81 typedef struct _ExpectedContentFrame {
82 const char *name;
83 const char *signature;
84 const char *file_name;
127 }
128
129 static jboolean check_sample_content(JNIEnv *env,
130 ObjectTrace* trace,
131 ExpectedContentFrame *expected,
132 size_t expected_count,
133 int print_out_comparisons) {
134 if (expected_count > trace->frame_count) {
135 return FALSE;
136 }
137
138 jvmtiFrameInfo* frames = trace->frames;
139
140 size_t i;
141 for (i = 0; i < expected_count; i++) {
142 // Get basic information out of the trace.
143 int bci = frames[i].location;
144 jmethodID methodid = frames[i].method;
145 char *name = NULL, *signature = NULL, *file_name = NULL;
146
147 if (bci < 0 && expected[i].line_number != -1) {
148 return FALSE;
149 }
150
151 // Transform into usable information.
152 int line_number = get_line_number(jvmti, methodid, bci);
153 (*jvmti)->GetMethodName(jvmti, methodid, &name, &signature, 0);
154
155 jclass declaring_class;
156 if (JVMTI_ERROR_NONE !=
157 (*jvmti)->GetMethodDeclaringClass(jvmti, methodid, &declaring_class)) {
158 return FALSE;
159 }
160
161 jvmtiError err = (*jvmti)->GetSourceFileName(jvmti, declaring_class,
162 &file_name);
163 if (err != JVMTI_ERROR_NONE) {
164 return FALSE;
165 }
166
167 // Compare now, none should be NULL.
221 string_id = (*env)->GetFieldID(env, frame_class, "fileName",
222 "Ljava/lang/String;");
223 string_object = (jstring) (*env)->GetObjectField(env, obj, string_id);
224 const char* file_name = (*env)->GetStringUTFChars(env, string_object, 0);
225
226 string_id = (*env)->GetFieldID(env, frame_class, "signature",
227 "Ljava/lang/String;");
228 string_object = (jstring) (*env)->GetObjectField(env, obj, string_id);
229 const char* signature= (*env)->GetStringUTFChars(env, string_object, 0);
230
231 native_frames[i].name = method;
232 native_frames[i].file_name = file_name;
233 native_frames[i].signature = signature;
234 native_frames[i].line_number = line_number;
235 }
236 }
237
238 // Internal storage system implementation.
239
240 static EventStorage global_event_storage;
241 static EventStorage second_global_event_storage;
242
243 static void event_storage_set_compaction_required(EventStorage* storage) {
244 pthread_mutex_lock(&storage->compaction_mutex);
245 storage->compaction_required = 1;
246 pthread_mutex_unlock(&storage->compaction_mutex);
247 }
248
249 static int event_storage_get_compaction_required(EventStorage* storage) {
250 pthread_mutex_lock(&storage->compaction_mutex);
251 int result = storage->compaction_required;
252 pthread_mutex_unlock(&storage->compaction_mutex);
253 return result;
254 }
255
256 static void event_storage_set_garbage_history(EventStorage* storage, int value) {
257 pthread_mutex_lock(&storage->storage_mutex);
258 global_event_storage.garbage_history_size = value;
259 free(global_event_storage.garbage_collected_objects);
260 size_t size =
261 sizeof(*global_event_storage.garbage_collected_objects) * value;
358 jlong size) {
359 jvmtiFrameInfo frames[64];
360 jint count;
361 jvmtiError err;
362
363 err = (*jvmti)->GetStackTrace(jvmti, thread, 0, 64, frames, &count);
364 if (err == JVMTI_ERROR_NONE && count >= 1) {
365 jvmtiFrameInfo* allocated_frames = (jvmtiFrameInfo*) malloc(count * sizeof(*allocated_frames));
366 memcpy(allocated_frames, frames, count * sizeof(*allocated_frames));
367
368 ObjectTrace* live_object = (ObjectTrace*) malloc(sizeof(*live_object));
369 live_object->frames = allocated_frames;
370 live_object->frame_count = count;
371 live_object->size = size;
372 live_object->thread = thread;
373 live_object->object = (*jni)->NewWeakGlobalRef(jni, object);
374
375 // Only now lock and get things done quickly.
376 pthread_mutex_lock(&storage->storage_mutex);
377
378 storage->live_object_additions++;
379
380 if (storage->live_object_count >= storage->live_object_size) {
381 event_storage_augment_storage(storage);
382 }
383 assert(storage->live_object_count < storage->live_object_size);
384
385 storage->live_objects[storage->live_object_count] = live_object;
386 storage->live_object_count++;
387
388 pthread_mutex_unlock(&storage->storage_mutex);
389 }
390 }
391
392 static void event_storage_compact(EventStorage* storage, JNIEnv* jni) {
393 pthread_mutex_lock(&storage->compaction_mutex);
394 storage->compaction_required = 0;
395 pthread_mutex_unlock(&storage->compaction_mutex);
396
397 pthread_mutex_lock(&storage->storage_mutex);
398
399 int max = storage->live_object_count;
414 }
415 }
416
417 storage->live_object_count = dest;
418 pthread_mutex_unlock(&storage->storage_mutex);
419 }
420
421 static void event_storage_free_objects(ObjectTrace** array, int max) {
422 int i;
423 for (i = 0; i < max; i++) {
424 free(array[i]), array[i] = NULL;
425 }
426 }
427
428 static void event_storage_reset(EventStorage* storage) {
429 pthread_mutex_lock(&storage->storage_mutex);
430
431 // Reset everything except the mutex and the garbage collection.
432 event_storage_free_objects(storage->live_objects,
433 storage->live_object_count);
434 storage->live_object_additions = 0;
435 storage->live_object_size = 0;
436 storage->live_object_count = 0;
437 free(storage->live_objects), storage->live_objects = NULL;
438
439 event_storage_free_objects(storage->garbage_collected_objects,
440 storage->garbage_history_size);
441
442 storage->compaction_required = 0;
443 storage->garbage_history_index = 0;
444
445 pthread_mutex_unlock(&storage->storage_mutex);
446 }
447
448 static int event_storage_number_additions(EventStorage* storage) {
449 pthread_mutex_lock(&storage->storage_mutex);
450 int result = storage->live_object_additions;
451 pthread_mutex_unlock(&storage->storage_mutex);
452 return result;
453 }
454
455 // Start of the JVMTI agent code.
456
457 static const char *EXC_CNAME = "java/lang/Exception";
458
459 static int check_error(jvmtiError err, const char *s) {
460 if (err != JVMTI_ERROR_NONE) {
461 printf(" ## %s error: %d\n", s, err);
462 return 1;
463 }
464 return 0;
465 }
466
467 static int check_capability_error(jvmtiError err, const char *s) {
468 if (err != JVMTI_ERROR_NONE) {
469 if (err == JVMTI_ERROR_MUST_POSSESS_CAPABILITY) {
470 return 0;
471 }
472 printf(" ## %s error: %d\n", s, err);
473 return 1;
474 }
503 return JNI_VERSION_1_8;
504 }
505
506 JNIEXPORT
507 void JNICALL SampledObjectAlloc(jvmtiEnv *jvmti_env,
508 JNIEnv* jni_env,
509 jthread thread,
510 jobject object,
511 jclass object_klass,
512 jlong size) {
513 if (event_storage_get_compaction_required(&global_event_storage)) {
514 event_storage_compact(&global_event_storage, jni_env);
515 }
516
517 jvmtiThreadInfo first_info;
518 event_storage_add(&global_event_storage, jni_env, thread, object,
519 object_klass, size);
520 }
521
522 JNIEXPORT
523 void JNICALL VMObjectAlloc(jvmtiEnv *jvmti_env,
524 JNIEnv* jni_env,
525 jthread thread,
526 jobject object,
527 jclass object_klass,
528 jlong size) {
529 event_storage_add(&second_global_event_storage, jni_env, thread, object,
530 object_klass, size);
531 }
532
533 JNIEXPORT
534 void JNICALL GarbageCollectionFinish(jvmtiEnv *jvmti_env) {
535 event_storage_set_compaction_required(&global_event_storage);
536 }
537
538 static int enable_notifications() {
539 if (check_error((*jvmti)->SetEventNotificationMode(
540 jvmti, JVMTI_ENABLE, JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, NULL),
541 "Set event notifications")) {
542 return 1;
543 }
544
545 return check_error((*jvmti)->SetEventNotificationMode(
546 jvmti, JVMTI_ENABLE, JVMTI_EVENT_SAMPLED_OBJECT_ALLOC, NULL),
547 "Set event notifications");
548 }
549
550 static int enable_notifications_for_two_threads(jthread first, jthread second) {
551 if (check_error((*jvmti)->SetEventNotificationMode(
552 jvmti, JVMTI_ENABLE, JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, NULL),
553 "Set event notifications")) {
576
577 res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
578 JVMTI_VERSION_9);
579 if (res != JNI_OK || jvmti == NULL) {
580 fprintf(stderr, "Error: wrong result of a valid call to GetEnv!\n");
581 return JNI_ERR;
582 }
583
584 // Get second jvmti environment.
585 res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &second_jvmti),
586 JVMTI_VERSION_9);
587 if (res != JNI_OK || second_jvmti == NULL) {
588 fprintf(stderr, "Error: wrong result of a valid second call to GetEnv!\n");
589 return JNI_ERR;
590 }
591
592 pthread_mutex_init(&global_event_storage.storage_mutex, 0);
593 pthread_mutex_init(&global_event_storage.compaction_mutex, 0);
594 event_storage_set_garbage_history(&global_event_storage, 200);
595
596 pthread_mutex_init(&second_global_event_storage.storage_mutex, 0);
597 pthread_mutex_init(&second_global_event_storage.compaction_mutex, 0);
598 event_storage_set_garbage_history(&second_global_event_storage, 200);
599
600 jvmtiEventCallbacks callbacks;
601 memset(&callbacks, 0, sizeof(callbacks));
602 callbacks.SampledObjectAlloc = &SampledObjectAlloc;
603 callbacks.VMObjectAlloc = &VMObjectAlloc;
604 callbacks.GarbageCollectionFinish = &GarbageCollectionFinish;
605
606 jvmtiCapabilities caps;
607 memset(&caps, 0, sizeof(caps));
608 // Get line numbers, sample events, filename, and gc events for the tests.
609 caps.can_get_line_numbers = 1;
610 caps.can_generate_sampled_alloc_events = 1;
611 caps.can_generate_vm_object_alloc_events = 1;
612 caps.can_get_source_file_name = 1;
613 caps.can_generate_garbage_collection_events = 1;
614 if (check_error((*jvmti)->AddCapabilities(jvmti, &caps), "Add capabilities")) {
615 return JNI_ERR;
616 }
617
618 if (check_error((*jvmti)->SetEventCallbacks(jvmti, &callbacks,
619 sizeof(jvmtiEventCallbacks)),
620 " Set Event Callbacks")) {
621 return JNI_ERR;
622 }
623 return JNI_OK;
624 }
625
626 JNIEXPORT void JNICALL
627 Java_MyPackage_HeapMonitor_setSamplingRate(JNIEnv* env, jclass cls, jint value) {
628 (*jvmti)->SetHeapSamplingRate(jvmti, value);
629 }
630
631 JNIEXPORT jboolean JNICALL
669 fill_native_frames(env, frames, native_frames, size);
670 return event_storage_contains(env, &global_event_storage, native_frames, size);
671 }
672
673 JNIEXPORT jboolean JNICALL
674 Java_MyPackage_HeapMonitor_garbageContains(JNIEnv* env, jclass cls, jobjectArray frames) {
675 jsize size = (*env)->GetArrayLength(env, frames);
676 ExpectedContentFrame native_frames[size];
677 fill_native_frames(env, frames, native_frames, size);
678 return event_storage_garbage_contains(env, &global_event_storage, native_frames, size);
679 }
680
681 JNIEXPORT void JNICALL
682 Java_MyPackage_HeapMonitor_forceGarbageCollection(JNIEnv* env, jclass cls) {
683 check_error((*jvmti)->ForceGarbageCollection(jvmti),
684 "Forced Garbage Collection");
685 }
686
687 JNIEXPORT void JNICALL
688 Java_MyPackage_HeapMonitor_resetEventStorage(JNIEnv* env, jclass cls) {
689 event_storage_reset(&global_event_storage);
690 event_storage_reset(&second_global_event_storage);
691 }
692
693 JNIEXPORT jboolean JNICALL
694 Java_MyPackage_HeapMonitorNoCapabilityTest_allSamplingMethodsFail(JNIEnv *env,
695 jclass cls) {
696 jvmtiCapabilities caps;
697 memset(&caps, 0, sizeof(caps));
698 caps.can_generate_sampled_alloc_events = 1;
699 if (check_error((*jvmti)->RelinquishCapabilities(jvmti, &caps),
700 "Add capabilities\n")){
701 return FALSE;
702 }
703
704 if (check_capability_error((*jvmti)->SetHeapSamplingRate(jvmti, 1<<19),
705 "Set Heap Sampling Rate")) {
706 return FALSE;
707 }
708 return TRUE;
709 }
710
827 Java_MyPackage_HeapMonitorEventsForTwoThreadsTest_checkSamples(JNIEnv* env,
828 jclass cls) {
829 pthread_mutex_lock(&global_event_storage.storage_mutex);
830 jint trace_counter;
831
832 const int expected_num_threads = 2;
833 ThreadsFound thread_data;
834 thread_data.num_threads = 0;
835 thread_data.threads = malloc(sizeof(jthread) * expected_num_threads);
836 memset(thread_data.threads, 0, sizeof(jthread) * expected_num_threads);
837
838 find_threads_in_array(&thread_data, global_event_storage.live_objects,
839 global_event_storage.live_object_count);
840
841 pthread_mutex_unlock(&global_event_storage.storage_mutex);
842
843 int obtained_threads = thread_data.num_threads;
844 return obtained_threads == expected_num_threads;
845 }
846
847 JNIEXPORT
848 void JNICALL SampledObjectAlloc2(jvmtiEnv *jvmti_env,
849 JNIEnv* jni_env,
850 jthread thread,
851 jobject object,
852 jclass object_klass,
853 jlong size) {
854 event_storage_add(&second_global_event_storage, jni_env, thread, object,
855 object_klass, size);
856 }
857
858 JNIEXPORT jboolean JNICALL
859 Java_MyPackage_HeapMonitorTwoAgentsTest_enablingSamplingInSecondaryAgent(
860 JNIEnv* env, jclass cls) {
861 jvmtiCapabilities caps;
862 memset(&caps, 0, sizeof(caps));
863 caps.can_generate_sampled_alloc_events = 1;
864 if (check_error((*second_jvmti)->AddCapabilities(second_jvmti, &caps),
865 "Set the capability for second agent")) {
866 return FALSE;
867 }
868
869 jvmtiEventCallbacks callbacks;
870 memset(&callbacks, 0, sizeof(callbacks));
871 callbacks.SampledObjectAlloc = &SampledObjectAlloc2;
872
873 if (check_error((*second_jvmti)->SetEventCallbacks(second_jvmti, &callbacks,
874 sizeof(jvmtiEventCallbacks)),
875 " Set Event Callbacks for second agent")) {
876 return FALSE;
877 }
878
879 return TRUE;
880 }
881
882 JNIEXPORT jboolean JNICALL
883 Java_MyPackage_HeapMonitorTwoAgentsTest_obtainedEventsForBothAgents(
884 JNIEnv* env, jclass cls, jobjectArray frames) {
885 jsize size = (*env)->GetArrayLength(env, frames);
886 ExpectedContentFrame native_frames[size];
887 fill_native_frames(env, frames, native_frames, size);
888
889 int first_storage_contained_events =
890 event_storage_contains(env, &global_event_storage, native_frames, size);
891
892 int second_storage_contained_events =
893 event_storage_contains(env, &second_global_event_storage, native_frames, size);
894
895 return first_storage_contained_events && second_storage_contained_events;
896 }
897
898 JNIEXPORT void JNICALL
899 Java_MyPackage_HeapMonitorVMEventsTest_enableVMEvents(JNIEnv* env, jclass cls) {
900 check_error((*jvmti)->SetEventNotificationMode(
901 jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_OBJECT_ALLOC, NULL),
902 "Set vm event notifications");
903 }
904
905 JNIEXPORT jboolean JNICALL
906 Java_MyPackage_HeapMonitorVMEventsTest_vmStorageContained(
907 JNIEnv* env, jclass cls, jobjectArray frames) {
908 jsize size = (*env)->GetArrayLength(env, frames);
909 ExpectedContentFrame native_frames[size];
910 fill_native_frames(env, frames, native_frames, size);
911
912 return event_storage_contains(env, &second_global_event_storage, native_frames, size);
913 }
914
915 JNIEXPORT jint JNICALL
916 Java_MyPackage_HeapMonitorVMEventsTest_vmEvents(JNIEnv* env, jclass cls) {
917 return event_storage_number_additions(&second_global_event_storage);
918 }
919
920 JNIEXPORT jint JNICALL
921 Java_MyPackage_HeapMonitorVMEventsTest_sampledEvents(JNIEnv* env, jclass cls) {
922 return event_storage_number_additions(&global_event_storage);
923 }
924
925 #ifdef __cplusplus
926 }
927 #endif
|