< 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
rev 48564 : [mq]: update-spec
rev 48565 : [mq]: event


   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 


  24 #include <stdio.h>
  25 #include <stdlib.h>
  26 #include <string.h>
  27 #include "jvmti.h"
  28 
  29 #ifdef __cplusplus
  30 extern "C" {
  31 #endif
  32 
  33 #ifndef JNI_ENV_ARG
  34 
  35 #ifdef __cplusplus
  36 #define JNI_ENV_ARG(x, y) y
  37 #define JNI_ENV_PTR(x) x
  38 #else
  39 #define JNI_ENV_ARG(x,y) x, y
  40 #define JNI_ENV_PTR(x) (*x)
  41 #endif
  42 
  43 #endif
  44 
  45 #define TRUE 1
  46 #define FALSE 0
  47 #define PRINT_OUT 1
  48 #define MAX_TRACES 400
  49 
  50 static const char *EXC_CNAME = "java/lang/Exception";
  51 static jvmtiEnv *jvmti = NULL;






































































































  52 
  53 static int check_error(jvmtiError err, const char *s) {
  54   if (err != JVMTI_ERROR_NONE) {
  55     printf("  ## %s error: %d\n", s, err);
  56     return 1;
  57   }
  58   return 0;
  59 }
  60 
  61 static int check_capability_error(jvmtiError err, const char *s) {
  62   if (err != JVMTI_ERROR_NONE) {
  63     if (err == JVMTI_ERROR_MUST_POSSESS_CAPABILITY) {
  64       return 0;
  65     }
  66     printf("  ## %s error: %d\n", s, err);
  67     return 1;
  68   }
  69   return 1;
  70 }
  71 


  80   return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);
  81 }
  82 
  83 static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
  84 
  85 JNIEXPORT
  86 jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
  87   return Agent_Initialize(jvm, options, reserved);
  88 }
  89 
  90 JNIEXPORT
  91 jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
  92   return Agent_Initialize(jvm, options, reserved);
  93 }
  94 
  95 JNIEXPORT
  96 jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
  97   return JNI_VERSION_1_8;
  98 }
  99 











 100 static
 101 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
 102   jint res;
 103 
 104   res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
 105                                  JVMTI_VERSION_9);
 106   if (res != JNI_OK || jvmti == NULL) {
 107     printf("    Error: wrong result of a valid call to GetEnv!\n");
 108     return JNI_ERR;
 109   }
 110 
 111   jvmtiEventCallbacks callbacks;
 112   memset(&callbacks, 0, sizeof(callbacks));

 113 
 114   jvmtiCapabilities caps;
 115   memset(&caps, 0, sizeof(caps));
 116   // Get line numbers, sample heap, and filename for the test.
 117   caps.can_get_line_numbers = 1;
 118   caps.can_sample_heap = 1;

 119   caps.can_get_source_file_name = 1;
 120   if (check_error((*jvmti)->AddCapabilities(jvmti, &caps),
 121                   "Add capabilities\n")){
 122     return JNI_ERR;
 123   }

 124   if (check_error((*jvmti)->SetEventCallbacks(jvmti, &callbacks,
 125                                               sizeof(jvmtiEventCallbacks)),
 126                   " Set Event Callbacks")) {
 127     return JNI_ERR;
 128   }






 129   return JNI_OK;
 130 }
 131 
 132 // Given a method and a location, this method gets the line number.
 133 static
 134 jint get_line_number(jvmtiEnv *jvmti, jmethodID method,
 135                      jlocation location) {
 136   // Read the line number table.
 137   jvmtiLineNumberEntry *table_ptr = 0;
 138   jint line_number_table_entries;
 139   int jvmti_error = (*jvmti)->GetLineNumberTable(jvmti, method,
 140                                                  &line_number_table_entries,
 141                                                  &table_ptr);
 142 
 143   if (JVMTI_ERROR_NONE != jvmti_error) {
 144     return -1;
 145   }
 146   if (line_number_table_entries <= 0) {
 147     return -1;
 148   }


 153   // Go through all the line numbers...
 154   jint last_location = table_ptr[0].start_location;
 155   int l;
 156   for (l = 1; l < line_number_table_entries; l++) {
 157     // ... and if you see one that is in the right place for your
 158     // location, you've found the line number!
 159     if ((location < table_ptr[l].start_location) &&
 160         (location >= last_location)) {
 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 


 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   }


 456   fill_native_frames(env, frames, native_frames, size);
 457 
 458   if (jvmti == NULL) {
 459     throw_exc(env, "JVMTI client was not properly loaded!\n");
 460     return FALSE ;
 461   }
 462 
 463   if ((!frames_exist_live(env, native_frames, size, print_out)) &&
 464       (!frames_exist_recent(env, native_frames, size, print_out)) &&
 465       (!frames_exist_frequent(env, native_frames, size, print_out))) {
 466     return TRUE;
 467   }
 468   return FALSE;
 469 }
 470 
 471 JNIEXPORT void JNICALL
 472 Java_MyPackage_HeapMonitor_enableSampling(JNIEnv *env, jclass cls, int rate,
 473                                           int max_traces) {
 474   check_error((*jvmti)->StartHeapSampling(jvmti, rate, max_traces),
 475               "Start Heap Sampling");






 476 }
 477 
 478 JNIEXPORT void JNICALL
 479 Java_MyPackage_HeapMonitor_disableSampling(JNIEnv *env, jclass cls) {
 480   check_error((*jvmti)->StopHeapSampling(jvmti), "Stop Heap Sampling");







 481 }
 482 
 483 JNIEXPORT jboolean JNICALL
 484 Java_MyPackage_HeapMonitor_areSamplingStatisticsZero(JNIEnv *env, jclass cls) {
 485   jvmtiHeapSamplingStats stats;
 486   check_error((*jvmti)->GetHeapSamplingStats(jvmti, &stats),
 487               "Heap Sampling Statistics");
 488 
 489   jvmtiHeapSamplingStats zero;
 490   memset(&zero, 0, sizeof(zero));
 491   return memcmp(&stats, &zero, sizeof(zero)) == 0;
 492 }
 493 
 494 JNIEXPORT jboolean JNICALL
 495 Java_MyPackage_HeapMonitor_framesExistEverywhere(JNIEnv *env, jclass cls,
 496                                                  jobjectArray frames) {
 497   // We want the frames in each part.
 498   return checkAll(env, frames, PRINT_OUT);
 499 }
 500 


 745                                                             jclass cls) {
 746   jvmtiAllocTraceInfo* traces;
 747   jint trace_counter;
 748 
 749   jvmtiError error = (*jvmti)->GetLiveObjectAllocTraces(jvmti, &traces,
 750                                                         &trace_counter);
 751 
 752   if (error != JVMTI_ERROR_NONE) {
 753     return;
 754   }
 755 
 756   (*jvmti)->Deallocate(jvmti, (unsigned char*) traces);
 757 }
 758 
 759 static jboolean compare_traces(jvmtiAllocTraceInfo* traces,
 760                                int trace_count,
 761                                jvmtiAllocTraceInfo* other_traces,
 762                                int other_trace_count,
 763                                int print_out_comparisons) {
 764   if (trace_count != other_trace_count) {


 765     return FALSE;
 766   }
 767 
 768   int i;
 769   for (i = 0; i < trace_count; i++) {
 770     jvmtiAllocTraceInfo* trace = traces + i;
 771     jvmtiAllocTraceInfo* other_trace = other_traces + i;
 772 
 773     jvmtiStackInfo* stack_info = trace->stack_info;
 774     jvmtiStackInfo* other_stack_info = trace->stack_info;
 775 
 776     if (stack_info->frame_count != other_stack_info->frame_count) {

 777       return FALSE;
 778     }
 779 
 780     if (trace->size != other_trace->size) {

 781       return FALSE;
 782     }
 783 
 784     if (trace->thread_id != other_trace->thread_id) {

 785       return FALSE;
 786     }
 787 
 788     jvmtiFrameInfo* frames = stack_info->frame_buffer;
 789     jvmtiFrameInfo* other_frames = other_stack_info->frame_buffer;
 790     if (memcmp(frames, other_frames, sizeof(*frames) * stack_info->frame_count)) {

 791       return FALSE;
 792     }
 793   }
 794 
 795   return TRUE;
 796 }
 797 
 798 JNIEXPORT jboolean JNICALL
 799 Java_MyPackage_HeapMonitorCachedTest_cachedAndLiveAreSame(JNIEnv *env,
 800                                                           jclass cls) {
 801   // Get cached first, then get live (since live performs a GC).
 802   jvmtiAllocTraceInfo* cached_traces;
 803   jint cached_trace_counter;
 804   jvmtiError error =
 805       (*jvmti)->GetCachedLiveObjectAllocTraces(jvmti, &cached_traces,
 806                                                &cached_trace_counter);
 807 
 808   if (error != JVMTI_ERROR_NONE) {
 809     return FALSE;
 810   }


 814   error = (*jvmti)->GetLiveObjectAllocTraces(jvmti, &live_traces,
 815                                              &live_trace_counter);
 816 
 817   if (error != JVMTI_ERROR_NONE) {
 818     return FALSE;
 819   }
 820 
 821   int result = compare_traces(cached_traces, cached_trace_counter,
 822                               live_traces, live_trace_counter,
 823                               PRINT_OUT);
 824 
 825   if ((*jvmti)->Deallocate(jvmti, (unsigned char*) cached_traces) != JVMTI_ERROR_NONE) {
 826     return FALSE;
 827   }
 828   if ((*jvmti)->Deallocate(jvmti, (unsigned char*) live_traces) != JVMTI_ERROR_NONE) {
 829     return FALSE;
 830   }
 831   return result;
 832 }
 833 










 834 static long hash(long hash_code, long value) {
 835   return hash_code * 31 + value;
 836 }
 837 
 838 static long get_hash_code(jvmtiAllocTraceInfo* traces, jint trace_counter) {
 839   int hash_code = 17;
 840   int i, j;
 841 
 842   hash_code = hash(hash_code, trace_counter);
 843   for (i = 0; i < trace_counter; i++) {
 844     jvmtiAllocTraceInfo* trace = traces + i;
 845 
 846     hash_code = hash(hash_code, trace->size);
 847     hash_code = hash(hash_code, trace->thread_id);
 848 
 849     jvmtiStackInfo* stack_info = trace->stack_info;
 850     hash_code = hash(hash_code, stack_info->frame_count);
 851 
 852     int frame_count = stack_info->frame_count;
 853     jvmtiFrameInfo* frames = stack_info->frame_buffer;


 872                                                &cached_trace_counter);
 873 
 874   if (error != JVMTI_ERROR_NONE) {
 875     return 0;
 876   }
 877 
 878   long hash_code = get_hash_code(cached_traces, cached_trace_counter);
 879 
 880   if ((*jvmti)->Deallocate(jvmti, (unsigned char*) cached_traces) != JVMTI_ERROR_NONE) {
 881     return FALSE;
 882   }
 883 
 884   return hash_code;
 885 }
 886 
 887 JNIEXPORT jboolean JNICALL
 888 Java_MyPackage_HeapMonitorTest_framesAreNotLive(JNIEnv *env,
 889                                                 jclass cls,
 890                                                 jobjectArray frames) {
 891   return !check_and(env, frames, FALSE, FALSE, TRUE, PRINT_OUT);





































 892 }
 893 
 894 #ifdef __cplusplus
 895 }
 896 #endif


   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 #include <assert.h>
  25 #include <pthread.h>
  26 #include <stdio.h>
  27 #include <stdlib.h>
  28 #include <string.h>
  29 #include "jvmti.h"
  30 
  31 #ifdef __cplusplus
  32 extern "C" {
  33 #endif
  34 
  35 #ifndef JNI_ENV_ARG
  36 
  37 #ifdef __cplusplus
  38 #define JNI_ENV_ARG(x, y) y
  39 #define JNI_ENV_PTR(x) x
  40 #else
  41 #define JNI_ENV_ARG(x,y) x, y
  42 #define JNI_ENV_PTR(x) (*x)
  43 #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 const char *EXC_CNAME = "java/lang/Exception";
  53 static jvmtiEnv *jvmti = NULL;
  54 static pthread_mutex_t event_data_lock;
  55 
  56 // Event storage code.
  57 
  58 typedef struct _LiveObjectTrace{
  59   jvmtiFrameInfo* frames;
  60   size_t frame_count;
  61 } LiveObjectTrace;
  62 
  63 typedef struct _EventStorage {
  64   int live_object_size;
  65   int live_object_count;
  66   LiveObjectTrace** live_objects;
  67 } EventStorage;
  68 
  69 typedef struct _ExpectedContentFrame {
  70   const char *name;
  71   const char *signature;
  72   const char *file_name;
  73   int line_number;
  74 } ExpectedContentFrame;
  75 
  76 static jboolean check_live_object_trace_content(
  77     JNIEnv *env, LiveObjectTrace* trace, ExpectedContentFrame *expected,
  78     size_t expected_count, int print_out_comparisons);
  79 
  80 static EventStorage global_event_storage;
  81 
  82 static int event_storage_get_count(EventStorage* storage) {
  83   return storage->live_object_count;
  84 }
  85 
  86 static jboolean event_storage_contains(JNIEnv* env,
  87                                        EventStorage* storage,
  88                                        ExpectedContentFrame* frames,
  89                                        size_t size) {
  90   int i;
  91   fprintf(stderr, "Event storage contains: %d\n", storage->live_object_count);
  92   for (i = 0; i < storage->live_object_count; i++) {
  93     LiveObjectTrace* trace = storage->live_objects[i];
  94 
  95     if (check_live_object_trace_content(env, trace, frames, size, PRINT_OUT)) {
  96       return TRUE;
  97     }
  98   }
  99   return FALSE;
 100 }
 101 
 102 static void event_storage_augment_storage(EventStorage* storage) {
 103   int new_max = (storage->live_object_size * 2) + 1;
 104   LiveObjectTrace** new_objects = malloc(new_max * sizeof(*new_objects));
 105 
 106   int current_count = storage->live_object_count;
 107   memcpy(new_objects, storage->live_objects, current_count * sizeof(*new_objects));
 108   free(storage->live_objects);
 109   storage->live_objects = new_objects;
 110 
 111   storage->live_object_size = new_max;
 112 }
 113 
 114 static void event_storage_add(EventStorage* storage,
 115                               jthread thread,
 116                               jobject object,
 117                               jclass klass,
 118                               jlong size) {
 119   pthread_mutex_lock(&event_data_lock);
 120   jvmtiFrameInfo frames[64];
 121   jint count;
 122   jvmtiError err;
 123   err = (*jvmti)->GetStackTrace(jvmti, thread, 0, 64, frames, &count);
 124   if (err == JVMTI_ERROR_NONE && count >= 1) {
 125     if (storage->live_object_count >= storage->live_object_size) {
 126       event_storage_augment_storage(storage);
 127     }
 128     assert(storage->live_object_count < storage->live_object_size);
 129 
 130     jvmtiFrameInfo* allocated_frames = malloc(count * sizeof(*allocated_frames));
 131     memcpy(allocated_frames, frames, count * sizeof(*allocated_frames));
 132 
 133     LiveObjectTrace* live_object = malloc(sizeof(*live_object));
 134     live_object->frames = allocated_frames;
 135     live_object->frame_count = count;
 136     storage->live_objects[storage->live_object_count] = live_object;
 137     storage->live_object_count++;
 138   }
 139   pthread_mutex_unlock(&event_data_lock);
 140 }
 141 
 142 static void event_storage_reset(EventStorage* storage) {
 143   pthread_mutex_lock(&event_data_lock);
 144   int max = storage->live_object_count;
 145   int i;
 146   for (i = 0; i < max; i++) {
 147     LiveObjectTrace* object = storage->live_objects[i];
 148     free(object);
 149   }
 150   free(storage->live_objects);
 151   memset(storage, 0, sizeof(*storage));
 152   pthread_mutex_unlock(&event_data_lock);
 153 }
 154 
 155 // General JVMTI agent code.
 156 
 157 static int check_error(jvmtiError err, const char *s) {
 158   if (err != JVMTI_ERROR_NONE) {
 159     printf("  ## %s error: %d\n", s, err);
 160     return 1;
 161   }
 162   return 0;
 163 }
 164 
 165 static int check_capability_error(jvmtiError err, const char *s) {
 166   if (err != JVMTI_ERROR_NONE) {
 167     if (err == JVMTI_ERROR_MUST_POSSESS_CAPABILITY) {
 168       return 0;
 169     }
 170     printf("  ## %s error: %d\n", s, err);
 171     return 1;
 172   }
 173   return 1;
 174 }
 175 


 184   return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);
 185 }
 186 
 187 static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
 188 
 189 JNIEXPORT
 190 jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
 191   return Agent_Initialize(jvm, options, reserved);
 192 }
 193 
 194 JNIEXPORT
 195 jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
 196   return Agent_Initialize(jvm, options, reserved);
 197 }
 198 
 199 JNIEXPORT
 200 jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
 201   return JNI_VERSION_1_8;
 202 }
 203 
 204 JNIEXPORT
 205 void JNICALL SampledObjectAlloc(jvmtiEnv *jvmti_env,
 206                                 JNIEnv* jni_env,
 207                                 jthread thread,
 208                                 jobject object,
 209                                 jclass object_klass,
 210                                 jlong size) {
 211   // Not optimal to do this at the callback but makes testing easier for now.
 212   event_storage_add(&global_event_storage, thread, object, object_klass, size);
 213 }
 214 
 215 static
 216 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
 217   jint res;
 218 
 219   res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
 220                                  JVMTI_VERSION_9);
 221   if (res != JNI_OK || jvmti == NULL) {
 222     printf("    Error: wrong result of a valid call to GetEnv!\n");
 223     return JNI_ERR;
 224   }
 225 
 226   jvmtiEventCallbacks callbacks;
 227   memset(&callbacks, 0, sizeof(callbacks));
 228   callbacks.SampledObjectAlloc = &SampledObjectAlloc;
 229 
 230   jvmtiCapabilities caps;
 231   memset(&caps, 0, sizeof(caps));
 232   // Get line numbers, sample heap, and filename for the test.
 233   caps.can_get_line_numbers = 1;
 234   caps.can_sample_heap = 1;
 235   caps.can_generate_sampled_object_alloc_events = 1;
 236   caps.can_get_source_file_name = 1;
 237   if (check_error((*jvmti)->AddCapabilities(jvmti, &caps),
 238                   "Add capabilities\n")){
 239     return JNI_ERR;
 240   }
 241 
 242   if (check_error((*jvmti)->SetEventCallbacks(jvmti, &callbacks,
 243                                               sizeof(jvmtiEventCallbacks)),
 244                   " Set Event Callbacks")) {
 245     return JNI_ERR;
 246   }
 247 
 248 
 249   if (pthread_mutex_init(&event_data_lock, NULL) != 0) {
 250     return JNI_ERR;
 251   }
 252 
 253   return JNI_OK;
 254 }
 255 
 256 // Given a method and a location, this method gets the line number.
 257 static
 258 jint get_line_number(jvmtiEnv *jvmti, jmethodID method,
 259                      jlocation location) {
 260   // Read the line number table.
 261   jvmtiLineNumberEntry *table_ptr = 0;
 262   jint line_number_table_entries;
 263   int jvmti_error = (*jvmti)->GetLineNumberTable(jvmti, method,
 264                                                  &line_number_table_entries,
 265                                                  &table_ptr);
 266 
 267   if (JVMTI_ERROR_NONE != jvmti_error) {
 268     return -1;
 269   }
 270   if (line_number_table_entries <= 0) {
 271     return -1;
 272   }


 277   // Go through all the line numbers...
 278   jint last_location = table_ptr[0].start_location;
 279   int l;
 280   for (l = 1; l < line_number_table_entries; l++) {
 281     // ... and if you see one that is in the right place for your
 282     // location, you've found the line number!
 283     if ((location < table_ptr[l].start_location) &&
 284         (location >= last_location)) {
 285       return table_ptr[l - 1].line_number;
 286     }
 287     last_location = table_ptr[l].start_location;
 288   }
 289 
 290   if (location >= last_location) {
 291     return table_ptr[line_number_table_entries - 1].line_number;
 292   } else {
 293     return -1;
 294   }
 295 }
 296 
 297 static jboolean check_frame_content(JNIEnv *env,
 298                                     jvmtiFrameInfo* frames,







 299                                     ExpectedContentFrame *expected,
 300                                     int expected_count,
 301                                     int print_out_comparisons) {
 302   int i;









 303   for (i = 0; i < expected_count; i++) {
 304     // Get basic information out of the trace.
 305     int bci = frames[i].location;
 306     jmethodID methodid = frames[i].method;
 307     char *name = NULL, *signature = NULL, *file_name = NULL;
 308 
 309     if (bci < 0) {
 310       return FALSE;
 311     }
 312 
 313     // Transform into usable information.
 314     int line_number = get_line_number(jvmti, methodid, bci);
 315     (*jvmti)->GetMethodName(jvmti, methodid, &name, &signature, 0);
 316 
 317     jclass declaring_class;
 318     if (JVMTI_ERROR_NONE !=
 319         (*jvmti)->GetMethodDeclaringClass(jvmti, methodid, &declaring_class)) {
 320       return FALSE;
 321     }
 322 


 346       fprintf(stderr, "\t\tFile name: %s and %s\n", file_name, expected[i].file_name);
 347       fprintf(stderr, "\t\tLines: %d and %d\n", line_number, expected[i].line_number);
 348       fprintf(stderr, "\t\tResult is %d\n",
 349               (strcmp(name, expected[i].name) ||
 350                strcmp(signature, expected[i].signature) ||
 351                strcmp(file_name, expected[i].file_name) ||
 352                line_number != expected[i].line_number));
 353     }
 354 
 355     if (strcmp(name, expected[i].name) ||
 356         strcmp(signature, expected[i].signature) ||
 357         strcmp(file_name, expected[i].file_name) ||
 358         line_number != expected[i].line_number) {
 359       return FALSE;
 360     }
 361   }
 362 
 363   return TRUE;
 364 }
 365 
 366 static jboolean check_live_object_trace_content(
 367     JNIEnv *env, LiveObjectTrace* trace, ExpectedContentFrame *expected,
 368     size_t expected_count, int print_out_comparisons) {
 369 
 370   if (expected_count > trace->frame_count) {
 371     return FALSE;
 372   }
 373 
 374   return check_frame_content(env, trace->frames,
 375                              expected, expected_count, print_out_comparisons);
 376 }
 377 
 378 static jboolean check_sample_content(JNIEnv *env,
 379                                      jvmtiAllocTraceInfo* trace,
 380                                      ExpectedContentFrame *expected,
 381                                      int expected_count,
 382                                      int print_out_comparisons) {
 383   jvmtiStackInfo* stack_info = trace->stack_info;
 384 
 385   if (expected_count > stack_info->frame_count) {
 386     return FALSE;
 387   }
 388 
 389   return check_frame_content(env, stack_info->frame_buffer,
 390                              expected, expected_count, print_out_comparisons);
 391 }
 392 
 393 static jboolean compare_samples(JNIEnv* env, jvmtiAllocTraceInfo* traces,
 394                                 int trace_count,
 395                                 ExpectedContentFrame* expected_content,
 396                                 size_t size,
 397                                 int print_out_comparisons) {
 398   // We expect the code to record correctly the bci, retrieve the line
 399   // number, have the right method and the class name of the first frames.
 400   int i;
 401   if (print_out_comparisons) {
 402     fprintf(stderr, "\tNumber of traces: %d\n", print_out_comparisons);
 403   }
 404 
 405   for (i = 0; i < trace_count; i++) {
 406     jvmtiAllocTraceInfo* trace = traces + i;
 407     if (check_sample_content(env, trace, expected_content, size,
 408                              print_out_comparisons)) {
 409       // At least one frame matched what we were looking for.
 410       return TRUE;
 411     }
 412   }


 591   fill_native_frames(env, frames, native_frames, size);
 592 
 593   if (jvmti == NULL) {
 594     throw_exc(env, "JVMTI client was not properly loaded!\n");
 595     return FALSE ;
 596   }
 597 
 598   if ((!frames_exist_live(env, native_frames, size, print_out)) &&
 599       (!frames_exist_recent(env, native_frames, size, print_out)) &&
 600       (!frames_exist_frequent(env, native_frames, size, print_out))) {
 601     return TRUE;
 602   }
 603   return FALSE;
 604 }
 605 
 606 JNIEXPORT void JNICALL
 607 Java_MyPackage_HeapMonitor_enableSampling(JNIEnv *env, jclass cls, int rate,
 608                                           int max_traces) {
 609   check_error((*jvmti)->StartHeapSampling(jvmti, rate, max_traces),
 610               "Start Heap Sampling");
 611   check_error(
 612       (*jvmti)->SetEventNotificationMode(jvmti,
 613                                          JVMTI_ENABLE,
 614                                          JVMTI_EVENT_SAMPLED_OBJECT_ALLOC,
 615                                          NULL),
 616       "Start sampling events");
 617 }
 618 
 619 JNIEXPORT void JNICALL
 620 Java_MyPackage_HeapMonitor_disableSampling(JNIEnv *env, jclass cls) {
 621   check_error((*jvmti)->StopHeapSampling(jvmti), "Stop Heap Sampling");
 622 
 623   check_error(
 624       (*jvmti)->SetEventNotificationMode(jvmti,
 625                                          JVMTI_DISABLE,
 626                                          JVMTI_EVENT_SAMPLED_OBJECT_ALLOC,
 627                                          NULL),
 628       "Start sampling events");
 629 }
 630 
 631 JNIEXPORT jboolean JNICALL
 632 Java_MyPackage_HeapMonitor_areSamplingStatisticsZero(JNIEnv *env, jclass cls) {
 633   jvmtiHeapSamplingStats stats;
 634   check_error((*jvmti)->GetHeapSamplingStats(jvmti, &stats),
 635               "Heap Sampling Statistics");
 636 
 637   jvmtiHeapSamplingStats zero;
 638   memset(&zero, 0, sizeof(zero));
 639   return memcmp(&stats, &zero, sizeof(zero)) == 0;
 640 }
 641 
 642 JNIEXPORT jboolean JNICALL
 643 Java_MyPackage_HeapMonitor_framesExistEverywhere(JNIEnv *env, jclass cls,
 644                                                  jobjectArray frames) {
 645   // We want the frames in each part.
 646   return checkAll(env, frames, PRINT_OUT);
 647 }
 648 


 893                                                             jclass cls) {
 894   jvmtiAllocTraceInfo* traces;
 895   jint trace_counter;
 896 
 897   jvmtiError error = (*jvmti)->GetLiveObjectAllocTraces(jvmti, &traces,
 898                                                         &trace_counter);
 899 
 900   if (error != JVMTI_ERROR_NONE) {
 901     return;
 902   }
 903 
 904   (*jvmti)->Deallocate(jvmti, (unsigned char*) traces);
 905 }
 906 
 907 static jboolean compare_traces(jvmtiAllocTraceInfo* traces,
 908                                int trace_count,
 909                                jvmtiAllocTraceInfo* other_traces,
 910                                int other_trace_count,
 911                                int print_out_comparisons) {
 912   if (trace_count != other_trace_count) {
 913     fprintf(stderr, "Trace count not the same!\n %d %d",
 914             trace_count, other_trace_count);
 915     return FALSE;
 916   }
 917 
 918   int i;
 919   for (i = 0; i < trace_count; i++) {
 920     jvmtiAllocTraceInfo* trace = traces + i;
 921     jvmtiAllocTraceInfo* other_trace = other_traces + i;
 922 
 923     jvmtiStackInfo* stack_info = trace->stack_info;
 924     jvmtiStackInfo* other_stack_info = trace->stack_info;
 925 
 926     if (stack_info->frame_count != other_stack_info->frame_count) {
 927       fprintf(stderr, "Frame count not the same!\n");
 928       return FALSE;
 929     }
 930 
 931     if (trace->size != other_trace->size) {
 932       fprintf(stderr, "Size not the same!\n");
 933       return FALSE;
 934     }
 935 
 936     if (trace->thread_id != other_trace->thread_id) {
 937       fprintf(stderr, "Thread id not the same!\n");
 938       return FALSE;
 939     }
 940 
 941     jvmtiFrameInfo* frames = stack_info->frame_buffer;
 942     jvmtiFrameInfo* other_frames = other_stack_info->frame_buffer;
 943     if (memcmp(frames, other_frames, sizeof(*frames) * stack_info->frame_count)) {
 944       fprintf(stderr, "memcmp not the same!\n");
 945       return FALSE;
 946     }
 947   }
 948 
 949   return TRUE;
 950 }
 951 
 952 JNIEXPORT jboolean JNICALL
 953 Java_MyPackage_HeapMonitorCachedTest_cachedAndLiveAreSame(JNIEnv *env,
 954                                                           jclass cls) {
 955   // Get cached first, then get live (since live performs a GC).
 956   jvmtiAllocTraceInfo* cached_traces;
 957   jint cached_trace_counter;
 958   jvmtiError error =
 959       (*jvmti)->GetCachedLiveObjectAllocTraces(jvmti, &cached_traces,
 960                                                &cached_trace_counter);
 961 
 962   if (error != JVMTI_ERROR_NONE) {
 963     return FALSE;
 964   }


 968   error = (*jvmti)->GetLiveObjectAllocTraces(jvmti, &live_traces,
 969                                              &live_trace_counter);
 970 
 971   if (error != JVMTI_ERROR_NONE) {
 972     return FALSE;
 973   }
 974 
 975   int result = compare_traces(cached_traces, cached_trace_counter,
 976                               live_traces, live_trace_counter,
 977                               PRINT_OUT);
 978 
 979   if ((*jvmti)->Deallocate(jvmti, (unsigned char*) cached_traces) != JVMTI_ERROR_NONE) {
 980     return FALSE;
 981   }
 982   if ((*jvmti)->Deallocate(jvmti, (unsigned char*) live_traces) != JVMTI_ERROR_NONE) {
 983     return FALSE;
 984   }
 985   return result;
 986 }
 987 
 988 JNIEXPORT jboolean JNICALL
 989 Java_MyPackage_HeapMonitorCachedTest_forceGC(JNIEnv *env, jclass cls) {
 990   jvmtiError error = (*jvmti)->ForceGarbageCollection(jvmti);
 991 
 992   if (error != JVMTI_ERROR_NONE) {
 993     return FALSE;
 994   }
 995   return TRUE;
 996 }
 997 
 998 static long hash(long hash_code, long value) {
 999   return hash_code * 31 + value;
1000 }
1001 
1002 static long get_hash_code(jvmtiAllocTraceInfo* traces, jint trace_counter) {
1003   int hash_code = 17;
1004   int i, j;
1005 
1006   hash_code = hash(hash_code, trace_counter);
1007   for (i = 0; i < trace_counter; i++) {
1008     jvmtiAllocTraceInfo* trace = traces + i;
1009 
1010     hash_code = hash(hash_code, trace->size);
1011     hash_code = hash(hash_code, trace->thread_id);
1012 
1013     jvmtiStackInfo* stack_info = trace->stack_info;
1014     hash_code = hash(hash_code, stack_info->frame_count);
1015 
1016     int frame_count = stack_info->frame_count;
1017     jvmtiFrameInfo* frames = stack_info->frame_buffer;


1036                                                &cached_trace_counter);
1037 
1038   if (error != JVMTI_ERROR_NONE) {
1039     return 0;
1040   }
1041 
1042   long hash_code = get_hash_code(cached_traces, cached_trace_counter);
1043 
1044   if ((*jvmti)->Deallocate(jvmti, (unsigned char*) cached_traces) != JVMTI_ERROR_NONE) {
1045     return FALSE;
1046   }
1047 
1048   return hash_code;
1049 }
1050 
1051 JNIEXPORT jboolean JNICALL
1052 Java_MyPackage_HeapMonitorTest_framesAreNotLive(JNIEnv *env,
1053                                                 jclass cls,
1054                                                 jobjectArray frames) {
1055   return !check_and(env, frames, FALSE, FALSE, TRUE, PRINT_OUT);
1056 }
1057 
1058 JNIEXPORT jboolean JNICALL
1059 Java_MyPackage_HeapMonitorEventNoCapabilityTest_eventSamplingFail(JNIEnv *env,
1060                                                                   jclass cls) {
1061   jvmtiCapabilities caps;
1062   memset(&caps, 0, sizeof(caps));
1063   caps.can_generate_sampled_object_alloc_events = 1;
1064   if (check_error((*jvmti)->RelinquishCapabilities(jvmti, &caps),
1065                   "Add capabilities\n")){
1066     return FALSE;
1067   }
1068 
1069   if (check_capability_error(
1070       (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_SAMPLED_OBJECT_ALLOC, NULL),
1071       "Set Tlab Heap Sampling")) {
1072     return FALSE;
1073   }
1074   return TRUE;
1075 }
1076 
1077 JNIEXPORT jboolean JNICALL
1078 Java_MyPackage_HeapMonitor_eventStorageIsEmpty(JNIEnv* env, jclass cls) {
1079   return event_storage_get_count(&global_event_storage) == 0;
1080 }
1081 
1082 JNIEXPORT jboolean JNICALL
1083 Java_MyPackage_HeapMonitor_obtainedEvents(JNIEnv* env, jclass cls, jobjectArray frames) {
1084   jsize size = (*env)->GetArrayLength(env, frames);
1085   ExpectedContentFrame native_frames[size];
1086   fill_native_frames(env, frames, native_frames, size);
1087   return event_storage_contains(env, &global_event_storage, native_frames, size);
1088 }
1089 
1090 JNIEXPORT void JNICALL
1091 Java_MyPackage_HeapMonitor_resetEventStorage(JNIEnv* env, jclass cls) {
1092   return event_storage_reset(&global_event_storage);
1093 }
1094 
1095 #ifdef __cplusplus
1096 }
1097 #endif
< prev index next >