< prev index next >

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

Print this page
rev 48551 : [mq]: heap8
rev 48552 : [mq]: heap10a
rev 48553 : [mq]: heap14_rebased
rev 48556 : [mq]: heap17
rev 48557 : [mq]: heap17
rev 48560 : [mq]: heap21
rev 48561 : [mq]: heap22
rev 48562 : [mq]: heap23


 161       return table_ptr[l - 1].line_number;
 162     }
 163     last_location = table_ptr[l].start_location;
 164   }
 165 
 166   if (location >= last_location) {
 167     return table_ptr[line_number_table_entries - 1].line_number;
 168   } else {
 169     return -1;
 170   }
 171 }
 172 
 173 typedef struct _ExpectedContentFrame {
 174   const char *name;
 175   const char *signature;
 176   const char *file_name;
 177   int line_number;
 178 } ExpectedContentFrame;
 179 
 180 static jboolean check_sample_content(JNIEnv *env,
 181                                      jvmtiStackTrace *trace,
 182                                      ExpectedContentFrame *expected,
 183                                      int expected_count,
 184                                      int print_out_comparisons) {
 185   int i;
 186 
 187   if (expected_count > trace->frame_count) {


 188     return FALSE;
 189   }
 190 


 191   for (i = 0; i < expected_count; i++) {
 192     // Get basic information out of the trace.
 193     int bci = trace->frames[i].location;
 194     jmethodID methodid = trace->frames[i].method;
 195     char *name = NULL, *signature = NULL, *file_name = NULL;
 196 
 197     if (bci < 0) {
 198       return FALSE;
 199     }
 200 
 201     // Transform into usable information.
 202     int line_number = get_line_number(jvmti, methodid, bci);
 203     (*jvmti)->GetMethodName(jvmti, methodid, &name, &signature, 0);
 204 
 205     jclass declaring_class;
 206     if (JVMTI_ERROR_NONE !=
 207         (*jvmti)->GetMethodDeclaringClass(jvmti, methodid, &declaring_class)) {
 208       return FALSE;
 209     }
 210 
 211     jvmtiError err = (*jvmti)->GetSourceFileName(jvmti, declaring_class,
 212                                                  &file_name);
 213     if (err != JVMTI_ERROR_NONE) {
 214       return FALSE;
 215     }
 216 
 217     // Compare now, none should be NULL.
 218     if (name == NULL) {
 219       return FALSE;
 220     }
 221 
 222     if (file_name == NULL) {
 223       return FALSE;
 224     }
 225 
 226     if (signature == NULL) {
 227       return FALSE;
 228     }
 229 
 230     if (print_out_comparisons) {
 231       fprintf(stderr, "Comparing:\n");
 232       fprintf(stderr, "\tNames: %s and %s\n", name, expected[i].name);
 233       fprintf(stderr, "\tSignatures: %s and %s\n", signature, expected[i].signature);
 234       fprintf(stderr, "\tFile name: %s and %s\n", file_name, expected[i].file_name);
 235       fprintf(stderr, "\tLines: %d and %d\n", line_number, expected[i].line_number);
 236       fprintf(stderr, "\tResult is %d\n",
 237               (strcmp(name, expected[i].name) ||
 238                strcmp(signature, expected[i].signature) ||
 239                strcmp(file_name, expected[i].file_name) ||
 240                line_number != expected[i].line_number));
 241     }
 242 
 243     if (strcmp(name, expected[i].name) ||
 244         strcmp(signature, expected[i].signature) ||
 245         strcmp(file_name, expected[i].file_name) ||
 246         line_number != expected[i].line_number) {
 247       return FALSE;
 248     }
 249   }
 250 
 251   return TRUE;
 252 }
 253 
 254 static jboolean compare_samples(JNIEnv* env, jvmtiStackTrace* traces,
 255                                 int trace_count,
 256                                 ExpectedContentFrame* expected_content,
 257                                 size_t size,
 258                                 int print_out_comparisons) {
 259   // We expect the code to record correctly the bci, retrieve the line
 260   // number, have the right method and the class name of the first frames.
 261   int i;




 262   for (i = 0; i < trace_count; i++) {
 263     jvmtiStackTrace *trace = traces + i;
 264     if (check_sample_content(env, trace, expected_content, size,
 265                              print_out_comparisons)) {
 266       // At least one frame matched what we were looking for.
 267       return TRUE;
 268     }
 269   }
 270 
 271   return FALSE;
 272 }
 273 
 274 static jboolean
 275 check_samples(JNIEnv* env,
 276               ExpectedContentFrame* expected,
 277               size_t size,
 278               jvmtiError (*const get_traces)(jvmtiEnv*, jvmtiStackTraces*),
 279               int print_out_comparisons) {
 280   jvmtiStackTraces traces;
 281   jvmtiError error = get_traces(jvmti, &traces);

 282 
 283   if (error != JVMTI_ERROR_NONE) {
 284     return FALSE;
 285   }
 286 
 287   int result = compare_samples(env, traces.stack_traces, traces.trace_count,
 288                                expected, size, print_out_comparisons);
 289   (*jvmti)->ReleaseTraces(jvmti, &traces);




 290   return result;
 291 }
 292 
 293 static jboolean frames_exist_live(JNIEnv* env,
 294                                   ExpectedContentFrame* expected,
 295                                   size_t size,
 296                                   int print_out_comparisons) {
 297   return check_samples(env, expected, size, (*jvmti)->GetLiveTraces,
 298                        print_out_comparisons);
 299 }
 300 
 301 static jboolean frames_exist_recent(JNIEnv* env,
 302                                     ExpectedContentFrame* expected,
 303                                     size_t size,
 304                                     int print_out_comparisons) {
 305   return check_samples(env, expected, size, (*jvmti)->GetGarbageTraces,
 306                        print_out_comparisons);
 307 }
 308 
 309 static jboolean frames_exist_frequent(JNIEnv* env,
 310                                       ExpectedContentFrame* expected,
 311                                       size_t size,
 312                                       int print_out_comparisons) {
 313   return check_samples(env, expected, size, (*jvmti)->GetFrequentGarbageTraces,
 314                        print_out_comparisons);
 315 }
 316 
 317 // Static native API for various tests.


 521                                                                   jclass cls) {
 522   jvmtiCapabilities caps;
 523   memset(&caps, 0, sizeof(caps));
 524   caps.can_sample_heap= 1;
 525   if (check_error((*jvmti)->RelinquishCapabilities(jvmti, &caps),
 526                   "Add capabilities\n")){
 527     return FALSE;
 528   }
 529 
 530   if (check_capability_error((*jvmti)->StartHeapSampling(jvmti, 1<<19,
 531                                                          MAX_TRACES),
 532                              "Start Heap Sampling")) {
 533     return FALSE;
 534   }
 535 
 536   if (check_capability_error((*jvmti)->StopHeapSampling(jvmti),
 537                              "Stop Heap Sampling")) {
 538     return FALSE;
 539   }
 540 
 541   if (check_capability_error((*jvmti)->ReleaseTraces(jvmti, NULL),
 542                              "Release Traces")) {
 543     return FALSE;
 544   }
 545 
 546   if (check_capability_error((*jvmti)->GetHeapSamplingStats(jvmti, NULL),
 547                              "Get Heap Sampling Stats")) {
 548     return FALSE;
 549   }
 550 
 551   if (check_capability_error((*jvmti)->GetGarbageTraces(jvmti, NULL),
 552                              "Get Garbage Traces")) {
 553     return FALSE;
 554   }
 555 
 556   if (check_capability_error((*jvmti)->GetFrequentGarbageTraces(jvmti, NULL),
 557                              "Get Frequent Garbage Traces")) {
 558     return FALSE;
 559   }
 560 
 561   if (check_capability_error((*jvmti)->GetLiveTraces(jvmti, NULL),
 562                              "Get Live Traces")) {





 563     return FALSE;
 564   }
 565   return TRUE;
 566 }
 567 
 568 JNIEXPORT jboolean JNICALL
 569 Java_MyPackage_HeapMonitor_statsHaveExpectedNumberSamples(JNIEnv *env,
 570                                                           jclass cls,
 571                                                           int expected,
 572                                                           int percent_error) {
 573   jvmtiHeapSamplingStats stats;
 574   check_error((*jvmti)->GetHeapSamplingStats(jvmti, &stats),
 575               "Heap Sampling Statistics");
 576 
 577   double diff_ratio = (stats.sample_count - expected);
 578   diff_ratio = (diff_ratio < 0) ? -diff_ratio : diff_ratio;
 579   diff_ratio /= expected;
 580 
 581   if (diff_ratio * 100 >= percent_error) {
 582     fprintf(stderr, "Problem with sample count, obtained %ld and expected %d\n",
 583             stats.sample_count, expected);
 584   }
 585   return diff_ratio * 100 < percent_error;
 586 }
 587 
 588 JNIEXPORT jdouble JNICALL
 589 Java_MyPackage_HeapMonitorStatRateTest_getAverageRate(JNIEnv *env, jclass cls) {
 590   jvmtiHeapSamplingStats stats;
 591   check_error((*jvmti)->GetHeapSamplingStats(jvmti, &stats),
 592               "Heap Sampling Statistics");
 593   return ((double) stats.sample_rate_accumulation) / stats.sample_rate_count;
 594 }
 595 
 596 static double calculate_average_stack_depth(
 597     jvmtiError (*const get_traces)(jvmtiEnv*, jvmtiStackTraces*)) {
 598   jvmtiStackTraces traces;

 599 
 600   jvmtiError error = get_traces(jvmti, &traces);;
 601 
 602   if (error != JVMTI_ERROR_NONE) {
 603     return 0;
 604   }
 605 
 606   int trace_count = traces.trace_count;
 607 
 608   if (trace_count == 0) {
 609     return 0;
 610   }
 611 
 612   int i;
 613   jvmtiStackTrace* stack_traces = traces.stack_traces;
 614   double sum = 0;
 615   for (i = 0; i < trace_count; i++) {
 616     jvmtiStackTrace *stack_trace = stack_traces + i;
 617     sum += stack_trace->frame_count;

 618   }
 619 
 620   if ((*jvmti)->ReleaseTraces(jvmti, &traces) != JVMTI_ERROR_NONE) {
 621     return 0;
 622   }
 623 
 624   return sum / i;
 625 }
 626 
 627 JNIEXPORT jdouble JNICALL
 628 Java_MyPackage_HeapMonitorStackDepthTest_getAverageStackDepth(JNIEnv *env,
 629                                                               jclass cls) {
 630   double result = calculate_average_stack_depth((*jvmti)->GetLiveTraces);
 631 
 632   if (result != 0) {
 633     return result;
 634   }
 635 
 636   // It is possible all the live objects got collected, check the garbage traces
 637   // in case.
 638   return calculate_average_stack_depth((*jvmti)->GetGarbageTraces);
 639 }
 640 
 641 typedef struct sThreadsFound {
 642   jint *threads;
 643   int num_threads;
 644 } ThreadsFound;
 645 
 646 static void find_threads_in_traces(jvmtiStackTraces* traces,

 647                                    ThreadsFound* thread_data) {
 648   int i;
 649   jvmtiStackTrace* stack_traces = traces->stack_traces;
 650   int trace_count = traces->trace_count;
 651 
 652   jint *threads = thread_data->threads;
 653   int num_threads = thread_data->num_threads;
 654 
 655   // We are looking for at last expected_num_threads different traces.
 656   for (i = 0; i < trace_count; i++) {
 657     jvmtiStackTrace *stack_trace = stack_traces + i;
 658     jlong thread_id = stack_trace->thread_id;

 659 
 660     // Check it is the right frame: only accept helper top framed traces.
 661     jmethodID methodid = stack_trace->frames[0].method;




 662     char *name = NULL, *signature = NULL, *file_name = NULL;
 663     (*jvmti)->GetMethodName(jvmti, methodid, &name, &signature, 0);
 664 
 665     if (strcmp(name, "helper")) {
 666       continue;
 667     }
 668 
 669     // Really not efficient look-up but it's for a test...
 670     int found = 0;
 671     int j;
 672     for (j = 0; j < num_threads; j++) {
 673       if (thread_id == threads[j]) {
 674         found = 1;
 675         break;
 676       }
 677     }
 678 
 679     if (!found) {
 680       threads[num_threads] = thread_id;
 681       num_threads++;
 682     }
 683   }
 684   thread_data->num_threads = num_threads;
 685 }
 686 
 687 JNIEXPORT jboolean JNICALL
 688 Java_MyPackage_HeapMonitorThreadTest_checkSamples(JNIEnv* env, jclass cls,
 689                                                   jintArray threads) {
 690   jvmtiStackTraces traces;


 691   ThreadsFound thread_data;
 692   thread_data.threads = (*env)->GetIntArrayElements(env, threads, 0);
 693   thread_data.num_threads = 0;
 694 
 695   // Get live and garbage traces to ensure we capture all the threads that have
 696   // been sampled.
 697   if ((*jvmti)->GetLiveTraces(jvmti, &traces) != JVMTI_ERROR_NONE) {
 698     return FALSE;
 699   }
 700 
 701   find_threads_in_traces(&traces, &thread_data);
 702 
 703   if ((*jvmti)->ReleaseTraces(jvmti, &traces) != JVMTI_ERROR_NONE) {
 704     return FALSE;
 705   }
 706 
 707   if ((*jvmti)->GetGarbageTraces(jvmti, &traces) != JVMTI_ERROR_NONE) {
 708     return FALSE;
 709   }
 710 
 711   find_threads_in_traces(&traces, &thread_data);
 712 
 713   if ((*jvmti)->ReleaseTraces(jvmti, &traces) != JVMTI_ERROR_NONE) {
 714     return FALSE;
 715   }
 716 
 717   (*env)->ReleaseIntArrayElements(env, threads, thread_data.threads, 0);
 718   return TRUE;
 719 }
 720 
 721 JNIEXPORT void JNICALL
 722 Java_MyPackage_HeapMonitorCachedTest_getLiveTracesToForceGc(JNIEnv *env,
 723                                                             jclass cls) {
 724   jvmtiStackTraces live_traces;
 725   jvmtiError error = (*jvmti)->GetLiveTraces(jvmti, &live_traces);



 726 
 727   if (error != JVMTI_ERROR_NONE) {
 728     return;
 729   }
 730 
 731   (*jvmti)->ReleaseTraces(jvmti, &live_traces);
 732 }
 733 
 734 static jboolean compare_traces(jvmtiStackTraces* traces,
 735                                jvmtiStackTraces* other_traces,


 736                                int print_out_comparisons) {
 737   int trace_count = traces->trace_count;
 738   if (trace_count != other_traces->trace_count) {
 739     return FALSE;
 740   }
 741 
 742   int i;
 743   for (i = 0; i < trace_count; i++) {
 744     jvmtiStackTrace* trace = traces->stack_traces + i;
 745     jvmtiStackTrace* other_trace = other_traces->stack_traces + i;



 746 
 747     if (trace->frame_count != other_trace->frame_count) {
 748       return FALSE;
 749     }
 750 
 751     if (trace->size != other_trace->size) {
 752       return FALSE;
 753     }
 754 
 755     if (trace->thread_id != other_trace->thread_id) {
 756       return FALSE;
 757     }
 758 
 759     jvmtiFrameInfo* frames = trace->frames;
 760     jvmtiFrameInfo* other_frames = other_trace->frames;
 761     if (memcmp(frames, other_frames, sizeof(*frames) * trace->frame_count)) {
 762       return FALSE;
 763     }
 764   }
 765 
 766   return TRUE;
 767 }
 768 
 769 JNIEXPORT jboolean JNICALL
 770 Java_MyPackage_HeapMonitorCachedTest_cachedAndLiveAreSame(JNIEnv *env,
 771                                                           jclass cls) {
 772   // Get cached first, then get live (since live performs a GC).
 773   jvmtiStackTraces cached_traces;
 774   jvmtiError error = (*jvmti)->GetCachedTraces(jvmti, &cached_traces);


 775 
 776   if (error != JVMTI_ERROR_NONE) {
 777     return FALSE;
 778   }
 779 
 780   jvmtiStackTraces live_traces;
 781   error = (*jvmti)->GetLiveTraces(jvmti, &live_traces);


 782 
 783   if (error != JVMTI_ERROR_NONE) {
 784     return FALSE;
 785   }
 786 
 787   int result = compare_traces(&cached_traces, &live_traces, PRINT_OUT);


 788 
 789   (*jvmti)->ReleaseTraces(jvmti, &cached_traces);
 790   (*jvmti)->ReleaseTraces(jvmti, &live_traces);




 791   return result;
 792 }
 793 
 794 static long hash(long hash_code, long value) {
 795   return hash_code * 31 + value;
 796 }
 797 
 798 static long get_hash_code(jvmtiStackTraces* traces) {
 799   int trace_count = traces->trace_count;
 800   int hash_code = 17;





 801 
 802   int i;
 803   hash_code = hash(hash_code, trace_count);
 804   for (i = 0; i < trace_count; i++) {
 805     jvmtiStackTrace* trace = traces->stack_traces + i;
 806     hash_code = hash(hash_code, trace->frame_count);
 807     hash_code = hash(hash_code, trace->size);
 808     hash_code = hash(hash_code, trace->thread_id);
 809 
 810     int j;
 811     int frame_count = trace->frame_count;
 812     jvmtiFrameInfo* frames = trace->frames;


 813     hash_code = hash(hash_code, frame_count);
 814     for (j = 0; j < frame_count; j++) {
 815       hash_code = hash(hash_code, (long) frames[i].method);
 816       hash_code = hash(hash_code, frames[i].location);
 817     }
 818   }
 819 
 820   return TRUE;
 821 }
 822 
 823 JNIEXPORT jlong JNICALL
 824 Java_MyPackage_HeapMonitorCachedTest_getCachedHashCode(JNIEnv *env,
 825                                                        jclass cls) {
 826   // Get cached first, then get live.
 827   jvmtiStackTraces cached_traces;
 828   jvmtiError error = (*jvmti)->GetCachedTraces(jvmti, &cached_traces);


 829 
 830   if (error != JVMTI_ERROR_NONE) {
 831     return 0;
 832   }
 833 
 834   long hash_code = get_hash_code(&cached_traces);
 835   (*jvmti)->ReleaseTraces(jvmti, &cached_traces);



 836 
 837   return hash_code;
 838 }
 839 
 840 JNIEXPORT jboolean JNICALL
 841 Java_MyPackage_HeapMonitorTest_framesAreNotLive(JNIEnv *env,
 842                                                 jclass cls,
 843                                                 jobjectArray frames) {
 844   return !check_and(env, frames, FALSE, FALSE, TRUE, PRINT_OUT);
 845 }
 846 
 847 #ifdef __cplusplus
 848 }
 849 #endif


 161       return table_ptr[l - 1].line_number;
 162     }
 163     last_location = table_ptr[l].start_location;
 164   }
 165 
 166   if (location >= last_location) {
 167     return table_ptr[line_number_table_entries - 1].line_number;
 168   } else {
 169     return -1;
 170   }
 171 }
 172 
 173 typedef struct _ExpectedContentFrame {
 174   const char *name;
 175   const char *signature;
 176   const char *file_name;
 177   int line_number;
 178 } ExpectedContentFrame;
 179 
 180 static jboolean check_sample_content(JNIEnv *env,
 181                                      jvmtiAllocTraceInfo* trace,
 182                                      ExpectedContentFrame *expected,
 183                                      int expected_count,
 184                                      int print_out_comparisons) {
 185   int i;
 186 
 187   jvmtiStackInfo* stack_info = trace->stack_info;
 188 
 189   if (expected_count > stack_info->frame_count) {
 190     return FALSE;
 191   }
 192 
 193   jvmtiFrameInfo* frames = stack_info->frame_buffer;
 194 
 195   for (i = 0; i < expected_count; i++) {
 196     // Get basic information out of the trace.
 197     int bci = frames[i].location;
 198     jmethodID methodid = frames[i].method;
 199     char *name = NULL, *signature = NULL, *file_name = NULL;
 200 
 201     if (bci < 0) {
 202       return FALSE;
 203     }
 204 
 205     // Transform into usable information.
 206     int line_number = get_line_number(jvmti, methodid, bci);
 207     (*jvmti)->GetMethodName(jvmti, methodid, &name, &signature, 0);
 208 
 209     jclass declaring_class;
 210     if (JVMTI_ERROR_NONE !=
 211         (*jvmti)->GetMethodDeclaringClass(jvmti, methodid, &declaring_class)) {
 212       return FALSE;
 213     }
 214 
 215     jvmtiError err = (*jvmti)->GetSourceFileName(jvmti, declaring_class,
 216                                                  &file_name);
 217     if (err != JVMTI_ERROR_NONE) {
 218       return FALSE;
 219     }
 220 
 221     // Compare now, none should be NULL.
 222     if (name == NULL) {
 223       return FALSE;
 224     }
 225 
 226     if (file_name == NULL) {
 227       return FALSE;
 228     }
 229 
 230     if (signature == NULL) {
 231       return FALSE;
 232     }
 233 
 234     if (print_out_comparisons) {
 235       fprintf(stderr, "\tComparing:\n");
 236       fprintf(stderr, "\t\tNames: %s and %s\n", name, expected[i].name);
 237       fprintf(stderr, "\t\tSignatures: %s and %s\n", signature, expected[i].signature);
 238       fprintf(stderr, "\t\tFile name: %s and %s\n", file_name, expected[i].file_name);
 239       fprintf(stderr, "\t\tLines: %d and %d\n", line_number, expected[i].line_number);
 240       fprintf(stderr, "\t\tResult is %d\n",
 241               (strcmp(name, expected[i].name) ||
 242                strcmp(signature, expected[i].signature) ||
 243                strcmp(file_name, expected[i].file_name) ||
 244                line_number != expected[i].line_number));
 245     }
 246 
 247     if (strcmp(name, expected[i].name) ||
 248         strcmp(signature, expected[i].signature) ||
 249         strcmp(file_name, expected[i].file_name) ||
 250         line_number != expected[i].line_number) {
 251       return FALSE;
 252     }
 253   }
 254 
 255   return TRUE;
 256 }
 257 
 258 static jboolean compare_samples(JNIEnv* env, jvmtiAllocTraceInfo* traces,
 259                                 int trace_count,
 260                                 ExpectedContentFrame* expected_content,
 261                                 size_t size,
 262                                 int print_out_comparisons) {
 263   // We expect the code to record correctly the bci, retrieve the line
 264   // number, have the right method and the class name of the first frames.
 265   int i;
 266   if (print_out_comparisons) {
 267     fprintf(stderr, "\tNumber of traces: %d\n", print_out_comparisons);
 268   }
 269 
 270   for (i = 0; i < trace_count; i++) {
 271     jvmtiAllocTraceInfo* trace = traces + i;
 272     if (check_sample_content(env, trace, expected_content, size,
 273                              print_out_comparisons)) {
 274       // At least one frame matched what we were looking for.
 275       return TRUE;
 276     }
 277   }
 278 
 279   return FALSE;
 280 }
 281 
 282 static jboolean
 283 check_samples(JNIEnv* env,
 284               ExpectedContentFrame* expected,
 285               size_t size,
 286               jvmtiError (*const get_traces)(jvmtiEnv*, jvmtiAllocTraceInfo**, jint*),
 287               int print_out_comparisons) {
 288   jvmtiAllocTraceInfo *traces;
 289   jint trace_counter;
 290   jvmtiError error = get_traces(jvmti, &traces, &trace_counter);
 291 
 292   if (error != JVMTI_ERROR_NONE) {
 293     return FALSE;
 294   }
 295 
 296   int result = compare_samples(env, traces, trace_counter,
 297                                expected, size, print_out_comparisons);
 298 
 299   if ((*jvmti)->Deallocate(jvmti, (unsigned char*) traces) != JVMTI_ERROR_NONE) {
 300     return FALSE;
 301   }
 302 
 303   return result;
 304 }
 305 
 306 static jboolean frames_exist_live(JNIEnv* env,
 307                                   ExpectedContentFrame* expected,
 308                                   size_t size,
 309                                   int print_out_comparisons) {
 310   return check_samples(env, expected, size, (*jvmti)->GetObjectAllocTraces,
 311                        print_out_comparisons);
 312 }
 313 
 314 static jboolean frames_exist_recent(JNIEnv* env,
 315                                     ExpectedContentFrame* expected,
 316                                     size_t size,
 317                                     int print_out_comparisons) {
 318   return check_samples(env, expected, size, (*jvmti)->GetGarbageTraces,
 319                        print_out_comparisons);
 320 }
 321 
 322 static jboolean frames_exist_frequent(JNIEnv* env,
 323                                       ExpectedContentFrame* expected,
 324                                       size_t size,
 325                                       int print_out_comparisons) {
 326   return check_samples(env, expected, size, (*jvmti)->GetFrequentGarbageTraces,
 327                        print_out_comparisons);
 328 }
 329 
 330 // Static native API for various tests.


 534                                                                   jclass cls) {
 535   jvmtiCapabilities caps;
 536   memset(&caps, 0, sizeof(caps));
 537   caps.can_sample_heap= 1;
 538   if (check_error((*jvmti)->RelinquishCapabilities(jvmti, &caps),
 539                   "Add capabilities\n")){
 540     return FALSE;
 541   }
 542 
 543   if (check_capability_error((*jvmti)->StartHeapSampling(jvmti, 1<<19,
 544                                                          MAX_TRACES),
 545                              "Start Heap Sampling")) {
 546     return FALSE;
 547   }
 548 
 549   if (check_capability_error((*jvmti)->StopHeapSampling(jvmti),
 550                              "Stop Heap Sampling")) {
 551     return FALSE;
 552   }
 553 





 554   if (check_capability_error((*jvmti)->GetHeapSamplingStats(jvmti, NULL),
 555                              "Get Heap Sampling Stats")) {
 556     return FALSE;
 557   }
 558 
 559   if (check_capability_error((*jvmti)->GetGarbageTraces(jvmti, NULL, NULL),
 560                              "Get Garbage Traces")) {
 561     return FALSE;
 562   }
 563 
 564   if (check_capability_error((*jvmti)->GetFrequentGarbageTraces(jvmti, NULL, NULL),
 565                              "Get Frequent Garbage Traces")) {
 566     return FALSE;
 567   }
 568 
 569   if (check_capability_error((*jvmti)->GetObjectAllocTraces(jvmti, NULL, NULL),
 570                              "Get Object Allocated Traces")) {
 571     return FALSE;
 572   }
 573 
 574   if (check_capability_error((*jvmti)->GetObjectAllocTraces(jvmti, NULL, NULL),
 575                              "Get Cached Object Allocated Traces")) {
 576     return FALSE;
 577   }
 578   return TRUE;
 579 }
 580 
 581 JNIEXPORT jboolean JNICALL
 582 Java_MyPackage_HeapMonitor_statsHaveExpectedNumberSamples(JNIEnv *env,
 583                                                           jclass cls,
 584                                                           int expected,
 585                                                           int percent_error) {
 586   jvmtiHeapSamplingStats stats;
 587   check_error((*jvmti)->GetHeapSamplingStats(jvmti, &stats),
 588               "Heap Sampling Statistics");
 589 
 590   double diff_ratio = (stats.sample_count - expected);
 591   diff_ratio = (diff_ratio < 0) ? -diff_ratio : diff_ratio;
 592   diff_ratio /= expected;
 593 
 594   if (diff_ratio * 100 >= percent_error) {
 595     fprintf(stderr, "Problem with sample count, obtained %ld and expected %d\n",
 596             stats.sample_count, expected);
 597   }
 598   return diff_ratio * 100 < percent_error;
 599 }
 600 
 601 JNIEXPORT jdouble JNICALL
 602 Java_MyPackage_HeapMonitorStatRateTest_getAverageRate(JNIEnv *env, jclass cls) {
 603   jvmtiHeapSamplingStats stats;
 604   check_error((*jvmti)->GetHeapSamplingStats(jvmti, &stats),
 605               "Heap Sampling Statistics");
 606   return ((double) stats.sample_rate_accumulation) / stats.sample_rate_count;
 607 }
 608 
 609 static double calculate_average_stack_depth(
 610     jvmtiError (*const get_traces)(jvmtiEnv*, jvmtiAllocTraceInfo**, jint*)) {
 611   jvmtiAllocTraceInfo* traces = NULL;
 612   jint trace_counter;
 613 
 614   jvmtiError error = get_traces(jvmti, &traces, &trace_counter);;
 615 
 616   if (error != JVMTI_ERROR_NONE) {
 617     return 0;
 618   }
 619 
 620   if (trace_counter == 0) {


 621     return 0;
 622   }
 623 
 624   int i;

 625   double sum = 0;
 626   for (i = 0; i < trace_counter; i++) {
 627     jvmtiAllocTraceInfo* trace = traces + i;
 628     jvmtiStackInfo* stack_info = trace->stack_info;
 629     sum += stack_info->frame_count;
 630   }
 631 
 632   if ((*jvmti)->Deallocate(jvmti, (unsigned char*) traces) != JVMTI_ERROR_NONE) {
 633     return 0;
 634   }
 635 
 636   return sum / i;
 637 }
 638 
 639 JNIEXPORT jdouble JNICALL
 640 Java_MyPackage_HeapMonitorStackDepthTest_getAverageStackDepth(JNIEnv *env,
 641                                                               jclass cls) {
 642   double result = calculate_average_stack_depth((*jvmti)->GetObjectAllocTraces);
 643 
 644   if (result != 0) {
 645     return result;
 646   }
 647 
 648   // It is possible all the live objects got collected, check the garbage traces
 649   // in case.
 650   return calculate_average_stack_depth((*jvmti)->GetGarbageTraces);
 651 }
 652 
 653 typedef struct sThreadsFound {
 654   jint* threads;
 655   int num_threads;
 656 } ThreadsFound;
 657 
 658 static void find_threads_in_traces(jvmtiAllocTraceInfo* traces,
 659                                    jint trace_counter,
 660                                    ThreadsFound* thread_data) {
 661   int i;
 662   jint* threads = thread_data->threads;



 663   int num_threads = thread_data->num_threads;
 664 
 665   // We are looking for at last expected_num_threads different traces.
 666   for (i = 0; i < trace_counter; i++) {
 667     jvmtiAllocTraceInfo* trace = traces + i;
 668     jvmtiStackInfo* stack_info = trace->stack_info;
 669     jint thread_id = trace->thread_id;
 670 
 671     // Check it is the right frame: only accept helper top framed traces.
 672     if (stack_info->frame_count == 0) {
 673       continue;
 674     }
 675 
 676     jmethodID methodid = stack_info->frame_buffer[0].method;
 677     char *name = NULL, *signature = NULL, *file_name = NULL;
 678     (*jvmti)->GetMethodName(jvmti, methodid, &name, &signature, 0);
 679 
 680     if (strcmp(name, "helper")) {
 681       continue;
 682     }
 683 
 684     // Really not efficient look-up but it's for a test...
 685     int found = 0;
 686     int j;
 687     for (j = 0; j < num_threads; j++) {
 688       if (thread_id == threads[j]) {
 689         found = 1;
 690         break;
 691       }
 692     }
 693 
 694     if (!found) {
 695       threads[num_threads] = thread_id;
 696       num_threads++;
 697     }
 698   }
 699   thread_data->num_threads = num_threads;
 700 }
 701 
 702 JNIEXPORT jboolean JNICALL
 703 Java_MyPackage_HeapMonitorThreadTest_checkSamples(JNIEnv* env, jclass cls,
 704                                                   jintArray threads) {
 705   jvmtiAllocTraceInfo* traces;
 706   jint trace_counter;
 707 
 708   ThreadsFound thread_data;
 709   thread_data.threads = (*env)->GetIntArrayElements(env, threads, 0);
 710   thread_data.num_threads = 0;
 711 
 712   // Get live and garbage traces to ensure we capture all the threads that have
 713   // been sampled.
 714   if ((*jvmti)->GetObjectAllocTraces(jvmti, &traces, &trace_counter) != JVMTI_ERROR_NONE) {
 715     return FALSE;
 716   }
 717 
 718   find_threads_in_traces(traces, trace_counter, &thread_data);
 719 
 720   if ((*jvmti)->Deallocate(jvmti, (unsigned char*) traces) != JVMTI_ERROR_NONE) {
 721     return FALSE;
 722   }
 723 
 724   if ((*jvmti)->GetGarbageTraces(jvmti, &traces, &trace_counter) != JVMTI_ERROR_NONE) {
 725     return FALSE;
 726   }
 727 
 728   find_threads_in_traces(traces, trace_counter, &thread_data);
 729 
 730   if ((*jvmti)->Deallocate(jvmti, (unsigned char*) traces) != JVMTI_ERROR_NONE) {
 731     return FALSE;
 732   }
 733 
 734   (*env)->ReleaseIntArrayElements(env, threads, thread_data.threads, 0);
 735   return TRUE;
 736 }
 737 
 738 JNIEXPORT void JNICALL
 739 Java_MyPackage_HeapMonitorCachedTest_getLiveTracesToForceGc(JNIEnv *env,
 740                                                             jclass cls) {
 741   jvmtiAllocTraceInfo* traces;
 742   jint trace_counter;
 743 
 744   jvmtiError error = (*jvmti)->GetObjectAllocTraces(jvmti, &traces,
 745                                                     &trace_counter);
 746 
 747   if (error != JVMTI_ERROR_NONE) {
 748     return;
 749   }
 750 
 751   (*jvmti)->Deallocate(jvmti, (unsigned char*) traces);
 752 }
 753 
 754 static jboolean compare_traces(jvmtiAllocTraceInfo* traces,
 755                                int trace_count,
 756                                jvmtiAllocTraceInfo* other_traces,
 757                                int other_trace_count,
 758                                int print_out_comparisons) {
 759   if (trace_count != other_trace_count) {

 760     return FALSE;
 761   }
 762 
 763   int i;
 764   for (i = 0; i < trace_count; i++) {
 765     jvmtiAllocTraceInfo* trace = traces + i;
 766     jvmtiAllocTraceInfo* other_trace = other_traces + i;
 767 
 768     jvmtiStackInfo* stack_info = trace->stack_info;
 769     jvmtiStackInfo* other_stack_info = trace->stack_info;
 770 
 771     if (stack_info->frame_count != other_stack_info->frame_count) {
 772       return FALSE;
 773     }
 774 
 775     if (trace->size != other_trace->size) {
 776       return FALSE;
 777     }
 778 
 779     if (trace->thread_id != other_trace->thread_id) {
 780       return FALSE;
 781     }
 782 
 783     jvmtiFrameInfo* frames = stack_info->frame_buffer;
 784     jvmtiFrameInfo* other_frames = other_stack_info->frame_buffer;
 785     if (memcmp(frames, other_frames, sizeof(*frames) * stack_info->frame_count)) {
 786       return FALSE;
 787     }
 788   }
 789 
 790   return TRUE;
 791 }
 792 
 793 JNIEXPORT jboolean JNICALL
 794 Java_MyPackage_HeapMonitorCachedTest_cachedAndLiveAreSame(JNIEnv *env,
 795                                                           jclass cls) {
 796   // Get cached first, then get live (since live performs a GC).
 797   jvmtiAllocTraceInfo* cached_traces;
 798   jint cached_trace_counter;
 799   jvmtiError error = (*jvmti)->GetCachedObjectAllocTraces(jvmti, &cached_traces,
 800                                                           &cached_trace_counter);
 801 
 802   if (error != JVMTI_ERROR_NONE) {
 803     return FALSE;
 804   }
 805 
 806   jvmtiAllocTraceInfo* live_traces;
 807   jint live_trace_counter;
 808   error = (*jvmti)->GetObjectAllocTraces(jvmti, &live_traces,
 809                                          &live_trace_counter);
 810 
 811   if (error != JVMTI_ERROR_NONE) {
 812     return FALSE;
 813   }
 814 
 815   int result = compare_traces(cached_traces, cached_trace_counter,
 816                               live_traces, live_trace_counter,
 817                               PRINT_OUT);
 818 
 819   if ((*jvmti)->Deallocate(jvmti, (unsigned char*) cached_traces) != JVMTI_ERROR_NONE) {
 820     return FALSE;
 821   }
 822   if ((*jvmti)->Deallocate(jvmti, (unsigned char*) live_traces) != JVMTI_ERROR_NONE) {
 823     return FALSE;
 824   }
 825   return result;
 826 }
 827 
 828 static long hash(long hash_code, long value) {
 829   return hash_code * 31 + value;
 830 }
 831 
 832 static long get_hash_code(jvmtiAllocTraceInfo* traces, jint trace_counter) {

 833   int hash_code = 17;
 834   int i, j;
 835 
 836   hash_code = hash(hash_code, trace_counter);
 837   for (i = 0; i < trace_counter; i++) {
 838     jvmtiAllocTraceInfo* trace = traces + i;
 839 





 840     hash_code = hash(hash_code, trace->size);
 841     hash_code = hash(hash_code, trace->thread_id);
 842 
 843     jvmtiStackInfo* stack_info = trace->stack_info;
 844     hash_code = hash(hash_code, stack_info->frame_count);
 845 
 846     int frame_count = stack_info->frame_count;
 847     jvmtiFrameInfo* frames = stack_info->frame_buffer;
 848     hash_code = hash(hash_code, frame_count);
 849     for (j = 0; j < frame_count; j++) {
 850       hash_code = hash(hash_code, (long) frames[i].method);
 851       hash_code = hash(hash_code, frames[i].location);
 852     }
 853   }
 854 
 855   return TRUE;
 856 }
 857 
 858 JNIEXPORT jlong JNICALL
 859 Java_MyPackage_HeapMonitorCachedTest_getCachedHashCode(JNIEnv *env,
 860                                                        jclass cls) {
 861   // Get cached first, then get live.
 862   jvmtiAllocTraceInfo* cached_traces;
 863   jint cached_trace_counter;
 864   jvmtiError error = (*jvmti)->GetCachedObjectAllocTraces(jvmti, &cached_traces,
 865                                                           &cached_trace_counter);
 866 
 867   if (error != JVMTI_ERROR_NONE) {
 868     return 0;
 869   }
 870 
 871   long hash_code = get_hash_code(cached_traces, cached_trace_counter);
 872 
 873   if ((*jvmti)->Deallocate(jvmti, (unsigned char*) cached_traces) != JVMTI_ERROR_NONE) {
 874     return FALSE;
 875   }
 876 
 877   return hash_code;
 878 }
 879 
 880 JNIEXPORT jboolean JNICALL
 881 Java_MyPackage_HeapMonitorTest_framesAreNotLive(JNIEnv *env,
 882                                                 jclass cls,
 883                                                 jobjectArray frames) {
 884   return !check_and(env, frames, FALSE, FALSE, TRUE, PRINT_OUT);
 885 }
 886 
 887 #ifdef __cplusplus
 888 }
 889 #endif
< prev index next >