< 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:
rev 52133 : [mq]: functional


 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   jvmtiError 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   jvmtiError err;
 743 
 744   err = (*jvmti)->GetThreadInfo(jvmti, thread, &info);
 745   if (err != JVMTI_ERROR_NONE) {
 746     fprintf(stderr, "Thread info for %p failed, ignoring thread count\n",
 747             thread);
 748     return;



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



 758   }
 759 
 760   thread_stats.threads[thread_stats.number_threads] = info.name;





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





 762   thread_stats.number_threads++;









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

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



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























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


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








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


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

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


< prev index next >