< prev index next >

test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.c

Print this page
rev 52132 : 8201655: Add thread-enabled support for the Heap Sampling
Summary:
Reviewed-by:


 684 JNIEXPORT
 685 jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
 686   return Agent_Initialize(jvm, options, reserved);
 687 }
 688 
 689 JNIEXPORT
 690 jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
 691   return Agent_Initialize(jvm, options, reserved);
 692 }
 693 
 694 JNIEXPORT
 695 jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
 696   return JNI_VERSION_1_8;
 697 }
 698 
 699 #define MAX_THREADS 500
 700 
 701 typedef struct ThreadStats {
 702   int number_threads;
 703   int counts[MAX_THREADS];
 704   int not_helper_counts[MAX_THREADS];
 705   int index[MAX_THREADS];
 706   jthread threads[MAX_THREADS];
 707 
 708   int method_resolution_problem;
 709 } ThreadStats;
 710 
 711 static ThreadStats thread_stats;
 712 
 713 static void add_thread_count(jthread thread, int lock, int helper) {


 714   int i;
 715   jvmtiThreadInfo info;
 716   const char* name;
 717   char* end;
 718   int idx;
 719   int err;


 720 
 721   if (lock) {
 722     event_storage_lock(&global_event_storage);




 723   }
 724 
 725   for (i = 0; i < thread_stats.number_threads; i++) {
 726     if (thread_stats.threads[i] == thread) {
 727       if (helper) {
 728         thread_stats.counts[i]++;
 729       } else {
 730         thread_stats.not_helper_counts[i]++;
 731       }
 732 
 733       if (lock) {
 734         event_storage_unlock(&global_event_storage);
 735       }
 736       return;
 737     }
 738   }


 739 
 740   thread_stats.threads[thread_stats.number_threads] = thread;






 741 
 742   err = (*jvmti)->GetThreadInfo(jvmti, thread, &info);
 743   if (err != JVMTI_ERROR_NONE) {
 744     if (lock) {
 745       event_storage_unlock(&global_event_storage);
 746     }
 747 
 748     // Just to have it accounted as an error...
 749     info.name = "Allocator99";
 750   }
 751 
 752   if (!strstr(info.name, "Allocator")) {
 753     if (lock) {


 754       event_storage_unlock(&global_event_storage);

 755     }
 756 
 757     // Just to have it accounted as an error...
 758     info.name = "Allocator98";
 759   }
 760 
 761   name = info.name + 9;
 762   end = NULL;
 763   idx = strtol(name, &end, 0);
 764 
 765   if (*end == '\0') {
 766     if (helper) {
 767       thread_stats.counts[thread_stats.number_threads]++;
 768     } else {
 769       thread_stats.not_helper_counts[thread_stats.number_threads]++;
 770     }
 771 
 772     thread_stats.index[thread_stats.number_threads] = idx;
 773     thread_stats.number_threads++;
 774   } else {
 775     fprintf(stderr, "Problem with thread name...: %p %s\n", thread, name);
 776   }
 777 
 778   if (PRINT_OUT) {
 779     fprintf(stderr, "Added %s - %p - %d - lock: %d\n", info.name, thread, idx, lock);
 780   }
 781 
 782   if (lock) {
 783     event_storage_unlock(&global_event_storage);
 784   }








 785 }
 786 
 787 static void print_thread_stats() {
 788   int i;
 789   event_storage_lock(&global_event_storage);
 790   fprintf(stderr, "Method resolution problem: %d\n", thread_stats.method_resolution_problem);
 791   fprintf(stderr, "Thread count:\n");
 792   for (i = 0; i < thread_stats.number_threads; i++) {
 793     fprintf(stderr, "\t%p: %d: %d - %d\n", thread_stats.threads[i],
 794             thread_stats.index[i],
 795             thread_stats.counts[i],
 796             thread_stats.not_helper_counts[i]);
 797   }
 798   event_storage_unlock(&global_event_storage);
 799 }
 800 
 801 JNIEXPORT
 802 void JNICALL SampledObjectAlloc(jvmtiEnv *jvmti_env,
 803                                 JNIEnv* jni_env,
 804                                 jthread thread,
 805                                 jobject object,
 806                                 jclass object_klass,
 807                                 jlong size) {
 808   add_thread_count(thread, 1, 1);
 809 
 810   if (event_storage_get_compaction_required(&global_event_storage)) {
 811     event_storage_compact(&global_event_storage, jni_env);
 812   }
 813 
 814   event_storage_add(&global_event_storage, jni_env, thread, object,
 815                     object_klass, size);
 816 }
 817 
 818 JNIEXPORT
 819 void JNICALL VMObjectAlloc(jvmtiEnv *jvmti_env,
 820                            JNIEnv* jni_env,
 821                            jthread thread,
 822                            jobject object,
 823                            jclass object_klass,
 824                            jlong size) {
 825   event_storage_add(&second_global_event_storage, jni_env, thread, object,
 826                     object_klass, size);
 827 }
 828 
 829 JNIEXPORT
 830 void JNICALL GarbageCollectionFinish(jvmtiEnv *jvmti_env) {
 831   event_storage_set_compaction_required(&global_event_storage);
 832 }
 833 
 834 static int enable_notifications() {
 835   if (check_error((*jvmti)->SetEventNotificationMode(
 836       jvmti, JVMTI_ENABLE, JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, NULL),
 837                      "Set event notifications")) {
 838     return 1;
 839   }
 840 
 841   return check_error((*jvmti)->SetEventNotificationMode(
 842       jvmti, JVMTI_ENABLE, JVMTI_EVENT_SAMPLED_OBJECT_ALLOC, NULL),
 843                      "Set event notifications");
 844 }
 845 
 846 static int enable_notifications_for_two_threads(jthread first, jthread second) {
 847   if (check_error((*jvmti)->SetEventNotificationMode(
 848       jvmti, JVMTI_ENABLE, JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, NULL),
 849                            "Set event notifications")) {
 850     return 0;
 851   }
 852 
 853   if (check_error((*jvmti)->SetEventNotificationMode(
 854       jvmti, JVMTI_ENABLE, JVMTI_EVENT_SAMPLED_OBJECT_ALLOC, first),
 855                   "Set event notifications")) {
 856     return 0;
 857   }
 858 
 859   // Second thread should fail.
 860   if (check_error((*jvmti)->SetEventNotificationMode(
 861       jvmti, JVMTI_ENABLE, JVMTI_EVENT_SAMPLED_OBJECT_ALLOC, second),
 862                   "Set event notifications")) {
 863     return 0;
 864   }
 865 
 866   return 1;
 867 }
 868 
 869 static
 870 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
 871   jint res;
 872   jvmtiEventCallbacks callbacks;
 873   jvmtiCapabilities caps;
 874 
 875   res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG3(jvm, (void **) &jvmti,
 876                                  JVMTI_VERSION_9));
 877   if (res != JNI_OK || jvmti == NULL) {
 878     fprintf(stderr, "Error: wrong result of a valid call to GetEnv!\n");
 879     return JNI_ERR;
 880   }
 881 
 882   // Get second jvmti environment.
 883   res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG3(jvm, (void **) &second_jvmti,
 884                                  JVMTI_VERSION_9));
 885   if (res != JNI_OK || second_jvmti == NULL) {
 886     fprintf(stderr, "Error: wrong result of a valid second call to GetEnv!\n");
 887     return JNI_ERR;
 888   }


 932 JNIEXPORT void JNICALL
 933 Java_MyPackage_HeapMonitor_setSamplingInterval(JNIEnv* env, jclass cls, jint value) {
 934   (*jvmti)->SetHeapSamplingInterval(jvmti, value);
 935 }
 936 
 937 JNIEXPORT jboolean JNICALL
 938 Java_MyPackage_HeapMonitor_eventStorageIsEmpty(JNIEnv* env, jclass cls) {
 939   return event_storage_get_count(&global_event_storage) == 0;
 940 }
 941 
 942 JNIEXPORT jint JNICALL
 943 Java_MyPackage_HeapMonitor_getEventStorageElementCount(JNIEnv* env, jclass cls) {
 944   return event_storage_get_count(&global_event_storage);
 945 }
 946 
 947 JNIEXPORT void JNICALL
 948 Java_MyPackage_HeapMonitor_enableSamplingEvents(JNIEnv* env, jclass cls) {
 949   enable_notifications();
 950 }
 951 
 952 JNIEXPORT jboolean JNICALL
 953 Java_MyPackage_HeapMonitor_enableSamplingEventsForTwoThreads(JNIEnv* env,
 954                                                              jclass cls,
 955                                                              jthread first,
 956                                                              jthread second) {
 957   return enable_notifications_for_two_threads(first, second);
 958 }
 959 
 960 JNIEXPORT void JNICALL
 961 Java_MyPackage_HeapMonitor_disableSamplingEvents(JNIEnv* env, jclass cls) {
 962   check_error((*jvmti)->SetEventNotificationMode(
 963       jvmti, JVMTI_DISABLE, JVMTI_EVENT_SAMPLED_OBJECT_ALLOC, NULL),
 964               "Set event notifications");
 965 
 966   check_error((*jvmti)->SetEventNotificationMode(
 967       jvmti, JVMTI_DISABLE, JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, NULL),
 968               "Garbage Collection Finish");
 969 }
 970 
 971 JNIEXPORT jboolean JNICALL
 972 Java_MyPackage_HeapMonitor_obtainedEvents(JNIEnv* env, jclass cls,
 973                                           jobjectArray frames,
 974                                           jboolean check_lines) {
 975   jboolean result;
 976   jsize size = JNI_ENV_PTR(env)->GetArrayLength(JNI_ENV_ARG2(env, frames));
 977   ExpectedContentFrame *native_frames;
 978 
 979   if (JNI_ENV_PTR(env)->ExceptionOccurred(JNI_ENV_ARG(env))) {


1082                    "Sampling interval -1024 passed\n")){
1083     return FALSE;
1084   }
1085 
1086   return TRUE;
1087 }
1088 
1089 JNIEXPORT jdouble JNICALL
1090 Java_MyPackage_HeapMonitor_getAverageSize(JNIEnv *env, jclass cls) {
1091   return event_storage_get_average_size(&global_event_storage);
1092 }
1093 
1094 typedef struct sThreadsFound {
1095   jthread* threads;
1096   int num_threads;
1097 } ThreadsFound;
1098 
1099 JNIEXPORT jboolean JNICALL
1100 Java_MyPackage_HeapMonitorThreadTest_checkSamples(JNIEnv* env, jclass cls,
1101                                                   jint num_threads) {
1102 
1103   print_thread_stats();
1104   // Ensure we got stacks from at least num_threads.
1105   return thread_stats.number_threads >= num_threads;
1106 }
1107 
1108 JNIEXPORT
1109 void JNICALL SampledObjectAlloc2(jvmtiEnv *jvmti_env,
1110                                  JNIEnv* jni_env,
1111                                  jthread thread,
1112                                  jobject object,
1113                                  jclass object_klass,
1114                                  jlong size) {
1115   // Nop for now, two agents are not yet implemented.
1116   assert(0);
1117 }
1118 
1119 JNIEXPORT jboolean JNICALL
1120 Java_MyPackage_HeapMonitorTwoAgentsTest_enablingSamplingInSecondaryAgent(
1121     JNIEnv* env, jclass cls) {
1122   // Currently this method should be failing directly at the AddCapability step




 684 JNIEXPORT
 685 jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
 686   return Agent_Initialize(jvm, options, reserved);
 687 }
 688 
 689 JNIEXPORT
 690 jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
 691   return Agent_Initialize(jvm, options, reserved);
 692 }
 693 
 694 JNIEXPORT
 695 jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
 696   return JNI_VERSION_1_8;
 697 }
 698 
 699 #define MAX_THREADS 500
 700 
 701 typedef struct ThreadStats {
 702   int number_threads;
 703   int counts[MAX_THREADS];
 704   char* threads[MAX_THREADS];




 705 } ThreadStats;
 706 
 707 static ThreadStats thread_stats;
 708 
 709 JNIEXPORT jboolean JNICALL
 710 Java_MyPackage_HeapMonitorThreadDisabledTest_checkThreadSamplesOnlyFrom(
 711     JNIEnv* env, jclass cls, jthread thread) {
 712   int i;
 713   jvmtiThreadInfo info;



 714   int err;
 715   char* expected_name;
 716   int found_thread = FALSE;
 717 
 718   err = (*jvmti)->GetThreadInfo(jvmti, thread, &info);
 719   expected_name = info.name;
 720 
 721   if (err != JVMTI_ERROR_NONE) {
 722     fprintf(stderr, "Failed to get thread information\n");
 723     return FALSE;
 724   }
 725 
 726   for (i = 0; i < thread_stats.number_threads; i++) {
 727     if (strcmp(expected_name, thread_stats.threads[i])) {
 728       return FALSE;

 729     } else {
 730       found_thread = TRUE;






 731     }
 732   }
 733   return found_thread;
 734 }
 735 
 736 static void add_thread_count(jthread thread) {
 737   int i;
 738   jvmtiThreadInfo info;
 739   const char* name;
 740   char* end;
 741   int idx;
 742   int err;
 743 
 744   err = (*jvmti)->GetThreadInfo(jvmti, thread, &info);
 745   if (err != JVMTI_ERROR_NONE) {
 746     return;





 747   }
 748 
 749   event_storage_lock(&global_event_storage);
 750   for (i = 0; i < thread_stats.number_threads; i++) {
 751     if (!strcmp(thread_stats.threads[i], info.name)) {
 752       thread_stats.counts[i]++;
 753       event_storage_unlock(&global_event_storage);
 754       return;
 755     }



 756   }
 757 
 758   thread_stats.threads[thread_stats.number_threads] = info.name;





 759   thread_stats.counts[thread_stats.number_threads]++;





 760   thread_stats.number_threads++;









 761   event_storage_unlock(&global_event_storage);
 762 }
 763 
 764 JNIEXPORT void JNICALL
 765 Java_MyPackage_HeapMonitorThreadDisabledTest_enableSamplingEvents(
 766     JNIEnv* env, jclass cls, jthread thread) {
 767   fprintf(stderr, "Enabling for %p\n", thread);
 768   check_error((*jvmti)->SetEventNotificationMode(
 769       jvmti, JVMTI_ENABLE, JVMTI_EVENT_SAMPLED_OBJECT_ALLOC, thread),
 770               "Set event notifications for a single thread");
 771 }
 772 
 773 static void print_thread_stats() {
 774   int i;
 775   event_storage_lock(&global_event_storage);

 776   fprintf(stderr, "Thread count:\n");
 777   for (i = 0; i < thread_stats.number_threads; i++) {
 778     fprintf(stderr, "\t%s: %d\n", thread_stats.threads[i], thread_stats.counts[i]);



 779   }
 780   event_storage_unlock(&global_event_storage);
 781 }
 782 
 783 JNIEXPORT
 784 void JNICALL SampledObjectAlloc(jvmtiEnv *jvmti_env,
 785                                 JNIEnv* jni_env,
 786                                 jthread thread,
 787                                 jobject object,
 788                                 jclass object_klass,
 789                                 jlong size) {
 790   add_thread_count(thread);
 791 
 792   if (event_storage_get_compaction_required(&global_event_storage)) {
 793     event_storage_compact(&global_event_storage, jni_env);
 794   }
 795 
 796   event_storage_add(&global_event_storage, jni_env, thread, object,
 797                     object_klass, size);
 798 }
 799 
 800 JNIEXPORT
 801 void JNICALL VMObjectAlloc(jvmtiEnv *jvmti_env,
 802                            JNIEnv* jni_env,
 803                            jthread thread,
 804                            jobject object,
 805                            jclass object_klass,
 806                            jlong size) {
 807   event_storage_add(&second_global_event_storage, jni_env, thread, object,
 808                     object_klass, size);
 809 }
 810 
 811 JNIEXPORT
 812 void JNICALL GarbageCollectionFinish(jvmtiEnv *jvmti_env) {
 813   event_storage_set_compaction_required(&global_event_storage);
 814 }
 815 
 816 static int enable_notifications() {
 817   if (check_error((*jvmti)->SetEventNotificationMode(
 818       jvmti, JVMTI_ENABLE, JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, NULL),
 819                      "Set event notifications")) {
 820     return 1;
 821   }
 822 
 823   return check_error((*jvmti)->SetEventNotificationMode(
 824       jvmti, JVMTI_ENABLE, JVMTI_EVENT_SAMPLED_OBJECT_ALLOC, NULL),
 825                      "Set event notifications");
 826 }
 827 























 828 static
 829 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
 830   jint res;
 831   jvmtiEventCallbacks callbacks;
 832   jvmtiCapabilities caps;
 833 
 834   res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG3(jvm, (void **) &jvmti,
 835                                  JVMTI_VERSION_9));
 836   if (res != JNI_OK || jvmti == NULL) {
 837     fprintf(stderr, "Error: wrong result of a valid call to GetEnv!\n");
 838     return JNI_ERR;
 839   }
 840 
 841   // Get second jvmti environment.
 842   res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG3(jvm, (void **) &second_jvmti,
 843                                  JVMTI_VERSION_9));
 844   if (res != JNI_OK || second_jvmti == NULL) {
 845     fprintf(stderr, "Error: wrong result of a valid second call to GetEnv!\n");
 846     return JNI_ERR;
 847   }


 891 JNIEXPORT void JNICALL
 892 Java_MyPackage_HeapMonitor_setSamplingInterval(JNIEnv* env, jclass cls, jint value) {
 893   (*jvmti)->SetHeapSamplingInterval(jvmti, value);
 894 }
 895 
 896 JNIEXPORT jboolean JNICALL
 897 Java_MyPackage_HeapMonitor_eventStorageIsEmpty(JNIEnv* env, jclass cls) {
 898   return event_storage_get_count(&global_event_storage) == 0;
 899 }
 900 
 901 JNIEXPORT jint JNICALL
 902 Java_MyPackage_HeapMonitor_getEventStorageElementCount(JNIEnv* env, jclass cls) {
 903   return event_storage_get_count(&global_event_storage);
 904 }
 905 
 906 JNIEXPORT void JNICALL
 907 Java_MyPackage_HeapMonitor_enableSamplingEvents(JNIEnv* env, jclass cls) {
 908   enable_notifications();
 909 }
 910 








 911 JNIEXPORT void JNICALL
 912 Java_MyPackage_HeapMonitor_disableSamplingEvents(JNIEnv* env, jclass cls) {
 913   check_error((*jvmti)->SetEventNotificationMode(
 914       jvmti, JVMTI_DISABLE, JVMTI_EVENT_SAMPLED_OBJECT_ALLOC, NULL),
 915               "Set event notifications");
 916 
 917   check_error((*jvmti)->SetEventNotificationMode(
 918       jvmti, JVMTI_DISABLE, JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, NULL),
 919               "Garbage Collection Finish");
 920 }
 921 
 922 JNIEXPORT jboolean JNICALL
 923 Java_MyPackage_HeapMonitor_obtainedEvents(JNIEnv* env, jclass cls,
 924                                           jobjectArray frames,
 925                                           jboolean check_lines) {
 926   jboolean result;
 927   jsize size = JNI_ENV_PTR(env)->GetArrayLength(JNI_ENV_ARG2(env, frames));
 928   ExpectedContentFrame *native_frames;
 929 
 930   if (JNI_ENV_PTR(env)->ExceptionOccurred(JNI_ENV_ARG(env))) {


1033                    "Sampling interval -1024 passed\n")){
1034     return FALSE;
1035   }
1036 
1037   return TRUE;
1038 }
1039 
1040 JNIEXPORT jdouble JNICALL
1041 Java_MyPackage_HeapMonitor_getAverageSize(JNIEnv *env, jclass cls) {
1042   return event_storage_get_average_size(&global_event_storage);
1043 }
1044 
1045 typedef struct sThreadsFound {
1046   jthread* threads;
1047   int num_threads;
1048 } ThreadsFound;
1049 
1050 JNIEXPORT jboolean JNICALL
1051 Java_MyPackage_HeapMonitorThreadTest_checkSamples(JNIEnv* env, jclass cls,
1052                                                   jint num_threads) {

1053   print_thread_stats();
1054   // Ensure we got stacks from at least num_threads.
1055   return thread_stats.number_threads >= num_threads;
1056 }
1057 
1058 JNIEXPORT
1059 void JNICALL SampledObjectAlloc2(jvmtiEnv *jvmti_env,
1060                                  JNIEnv* jni_env,
1061                                  jthread thread,
1062                                  jobject object,
1063                                  jclass object_klass,
1064                                  jlong size) {
1065   // Nop for now, two agents are not yet implemented.
1066   assert(0);
1067 }
1068 
1069 JNIEXPORT jboolean JNICALL
1070 Java_MyPackage_HeapMonitorTwoAgentsTest_enablingSamplingInSecondaryAgent(
1071     JNIEnv* env, jclass cls) {
1072   // Currently this method should be failing directly at the AddCapability step


< prev index next >