1 /*
   2  * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   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 /* This test case to test the following:
  25  *      StackTrace esp. new args
  26  */
  27 
  28 #include <stdio.h>
  29 #include <string.h>
  30 #include "jvmti.h"
  31 #include "agent_common.h"
  32 
  33 extern "C" {
  34 
  35 #define JVMTI_ERROR_CHECK(str,res) if ( res != JVMTI_ERROR_NONE) { printf(str); printf("%d\n",res); return res;}
  36 #define JVMTI_ERROR_CHECK_EXPECTED_ERROR(str,res,err) if ( res != err) { printf(str); printf("unexpected error %d\n",res); return res;}
  37 
  38 #define JVMTI_ERROR_CHECK_VOID(str,res) if ( res != JVMTI_ERROR_NONE) { printf(str); printf("%d\n",res); iGlobalStatus = 2; }
  39 
  40 #define JVMTI_ERROR_CHECK_EXPECTED_ERROR_VOID(str,res,err) if ( res != err) { printf(str); printf("unexpected error %d\n",res); iGlobalStatus = 2; }
  41 
  42 #define THREADS_LIMIT 2000
  43 
  44 
  45 jvmtiEnv *jvmti;
  46 jint iGlobalStatus = 0;
  47 jthread susp_thrd[THREADS_LIMIT];
  48 static jvmtiEventCallbacks callbacks;
  49 static jvmtiCapabilities jvmti_caps;
  50 jrawMonitorID jraw_monitor[20];
  51 
  52 int process_once = 0;
  53 
  54 
  55 
  56 int printdump = 0;
  57 
  58 
  59 void debug_printf(const char *fmt, ...) {
  60     va_list args;
  61 
  62     va_start(args, fmt);
  63     if (printdump) {
  64         vprintf(fmt, args);
  65     }
  66     va_end(args);
  67 }
  68 
  69 
  70 #ifdef STATIC_BUILD
  71 JNIEXPORT jint JNICALL Agent_OnLoad_JvmtiTest(JavaVM *jvm, char *options, void *reserved) {
  72     return Agent_Initialize(jvm, options, reserved);
  73 }
  74 JNIEXPORT jint JNICALL Agent_OnAttach_JvmtiTest(JavaVM *jvm, char *options, void *reserved) {
  75     return Agent_Initialize(jvm, options, reserved);
  76 }
  77 JNIEXPORT jint JNI_OnLoad_JvmtiTest(JavaVM *jvm, char *options, void *reserved) {
  78     return JNI_VERSION_1_8;
  79 }
  80 #endif
  81 jint Agent_Initialize(JavaVM * jvm, char *options, void *reserved) {
  82     jint res;
  83 
  84     if (options && strlen(options) > 0) {
  85         if (strstr(options, "printdump")) {
  86             printdump = 1;
  87         }
  88     }
  89 
  90     res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1);
  91     if (res < 0) {
  92         printf("Wrong result of a valid call to GetEnv!\n");
  93         return JNI_ERR;
  94     }
  95 
  96 
  97     /* Add capabilities */
  98     res = jvmti->GetPotentialCapabilities(&jvmti_caps);
  99     JVMTI_ERROR_CHECK("GetPotentialCapabilities returned error", res);
 100 
 101     res = jvmti->AddCapabilities(&jvmti_caps);
 102     JVMTI_ERROR_CHECK("GetPotentialCapabilities returned error", res);
 103 
 104     return JNI_OK;
 105 }
 106 
 107 
 108 JNIEXPORT jint JNICALL
 109 Java_nsk_jvmti_unit_StackTrace_JvmtiTest_GetResult(JNIEnv * env, jclass cls) {
 110     return iGlobalStatus;
 111 }
 112 
 113 
 114 JNIEXPORT void JNICALL
 115 Java_nsk_jvmti_unit_StackTrace_JvmtiTest_CreateRawMonitor(JNIEnv * env, jclass klass, jint i) {
 116     jvmtiError ret;
 117     char sz[128];
 118 
 119     sprintf(sz, "Rawmonitor-%d",i);
 120     debug_printf("jvmti create raw monitor \n");
 121     ret = jvmti->CreateRawMonitor(sz, &jraw_monitor[i]);
 122 
 123     if (ret != JVMTI_ERROR_NONE) {
 124         printf("Error: ForceGarbageCollection %d \n", ret);
 125         iGlobalStatus = 2;
 126     }
 127 }
 128 
 129 JNIEXPORT void JNICALL
 130 Java_nsk_jvmti_unit_StackTrace_JvmtiTest_RawMonitorEnter(JNIEnv * env, jclass cls, jint i) {
 131     jvmtiError ret;
 132 
 133     debug_printf("jvmti Raw monitor enter \n");
 134     ret = jvmti->RawMonitorEnter(jraw_monitor[i]);
 135 
 136     if (ret != JVMTI_ERROR_NONE) {
 137         printf("Error: Raw monitor enter %d \n", ret);
 138         iGlobalStatus = 2;
 139     }
 140 }
 141 
 142 JNIEXPORT void JNICALL
 143 Java_nsk_jvmti_unit_StackTrace_JvmtiTest_RawMonitorExit(JNIEnv * env, jclass cls, jint i) {
 144     jvmtiError ret;
 145 
 146     debug_printf("jvmti raw monitor exit \n");
 147     ret = jvmti->RawMonitorExit(jraw_monitor[i]);
 148 
 149     if (ret != JVMTI_ERROR_NONE) {
 150         printf("Error: RawMonitorExit %d \n", ret);
 151         iGlobalStatus = 2;
 152     }
 153 }
 154 
 155 JNIEXPORT void JNICALL
 156 Java_nsk_jvmti_unit_StackTrace_JvmtiTest_RawMonitorWait(JNIEnv * env, jclass cls, jint i) {
 157     jvmtiError ret;
 158 
 159     debug_printf("jvmti RawMonitorWait \n");
 160     ret = jvmti->RawMonitorWait(jraw_monitor[i], -1);
 161 
 162     if (ret != JVMTI_ERROR_NONE) {
 163         printf("Error: RawMonitorWait %d \n", ret);
 164         iGlobalStatus = 2;
 165     }
 166 }
 167 
 168 JNIEXPORT void JNICALL
 169 Java_nsk_jvmti_unit_StackTrace_JvmtiTest_RawMonitorNotify(JNIEnv * env, jclass cls, jint i) {
 170     jvmtiError ret;
 171 
 172     debug_printf("jvmti RawMonitorNotify \n");
 173     ret = jvmti->RawMonitorNotifyAll(jraw_monitor[i]);
 174 
 175     if (ret != JVMTI_ERROR_NONE) {
 176         printf("Error: RawMonitorNotify %d \n", ret);
 177         iGlobalStatus = 2;
 178     }
 179 }
 180 
 181 JNIEXPORT int JNICALL
 182 Java_nsk_jvmti_unit_StackTrace_JvmtiTest_GetFrameCount(JNIEnv * env, jclass cls, jobject thr) {
 183     jvmtiError ret;
 184     jint count;
 185 
 186     debug_printf("jvmti GetFrameCount \n");
 187     ret = jvmti->GetFrameCount((jthread) thr,  &count);
 188     if (ret != JVMTI_ERROR_NONE) {
 189         printf("Error: GetFrameCount returned  %d \n", ret);
 190         iGlobalStatus = 2;
 191     }
 192     return count;
 193 }
 194 
 195 JNIEXPORT void JNICALL
 196 Java_nsk_jvmti_unit_StackTrace_JvmtiTest_GetStackTrace(JNIEnv * env, jclass cls, jobject thr) {
 197     jvmtiError ret;
 198     jvmtiFrameInfo *stack_buffer = NULL;
 199     jvmtiFrameInfo *compare_buffer = NULL;
 200     jint max_count = 20;
 201     jint count;
 202     jclass klass;
 203     char *mname;
 204     char *signature;
 205     char *clname;
 206     int i;
 207     int j;
 208 
 209 
 210     debug_printf("jvmti GetStackTrace \n");
 211 
 212     ret = jvmti->Allocate(sizeof(jvmtiFrameInfo) * max_count, (unsigned char**)&stack_buffer);
 213     if (ret != JVMTI_ERROR_NONE) {
 214         printf("Error: Allocate failed with  %d \n", ret);
 215         iGlobalStatus = 2;
 216     }
 217 
 218     ret = jvmti->Allocate(sizeof(jvmtiFrameInfo) * max_count, (unsigned char**)&compare_buffer);
 219     if (ret != JVMTI_ERROR_NONE) {
 220         printf("Error: Allocate failed with  %d \n", ret);
 221         iGlobalStatus = 2;
 222     }
 223 
 224 
 225     ret = jvmti->SuspendThread(thr);
 226     if (ret != JVMTI_ERROR_NONE) {
 227         printf("Error: SuspendThread failed with  %d \n", ret);
 228         iGlobalStatus = 2;
 229     }
 230 
 231     ret = jvmti->GetStackTrace(thr, 0, max_count, stack_buffer, &count);
 232     if (ret != JVMTI_ERROR_NONE) {
 233         printf("Error: GetStackTrace %d \n", ret);
 234         iGlobalStatus = 2;
 235     }
 236 
 237     for (i = 1; i < count; ++i) {
 238       jint res_count = 48343;
 239       ret = jvmti->GetStackTrace(thr, i, max_count, compare_buffer, &res_count);
 240       if (ret != JVMTI_ERROR_NONE) {
 241         printf("Error: GetStackTrace2 %d \n", ret);
 242         iGlobalStatus = 2;
 243       }
 244       if (res_count != count - i) {
 245         printf("Error: mismatch res_count = %d, count = %d, i = %d\n", res_count, count, i);
 246         iGlobalStatus = 2;
 247       }
 248       for (j = 0; j < res_count; j++) {
 249         if (compare_buffer[j].method != stack_buffer[j+i].method) {
 250             printf("Error: wrong method\n");
 251             iGlobalStatus = 2;
 252         }
 253       }
 254     }
 255 
 256     for (i = 1; i < count; ++i) {
 257       jint res_count = 48343;
 258       ret = jvmti->GetStackTrace(thr, -i, max_count, compare_buffer, &res_count);
 259       if (ret != JVMTI_ERROR_NONE) {
 260         printf("Error: GetStackTrace2 %d \n", ret);
 261         iGlobalStatus = 2;
 262       }
 263       if (res_count != i) {
 264         printf("Error: mismatch res_count = %d, i = %d\n", res_count, i);
 265         iGlobalStatus = 2;
 266       }
 267       for (j = 0; j < res_count; j++) {
 268         if (compare_buffer[j].method != stack_buffer[j+count-i].method) {
 269             printf("Error: wrong neg method\n");
 270             iGlobalStatus = 2;
 271         }
 272       }
 273     }
 274 
 275     debug_printf("Count = %d\n", count);
 276 
 277 
 278     ret = jvmti->ResumeThread(thr);
 279     if (ret != JVMTI_ERROR_NONE) {
 280         printf("Error: ResumeThread failed with  %d \n", ret);
 281         iGlobalStatus = 2;
 282     }
 283 
 284     debug_printf(" Java Stack trace ---\n");
 285 
 286     for (i = 0; i < count; i++) {
 287         ret = jvmti->GetMethodDeclaringClass(stack_buffer[i].method, &klass);
 288         if (ret != JVMTI_ERROR_NONE) {
 289             printf("Error: GetMethodDeclaringClass %d  \n", ret);
 290             iGlobalStatus = 2;
 291             return;
 292         }
 293 
 294         ret = jvmti->GetClassSignature(klass, &clname, NULL);
 295         if (ret != JVMTI_ERROR_NONE) {
 296             printf("Error: GetClassSignature %d  \n", ret);
 297             iGlobalStatus = 2;
 298             return;
 299         }
 300 
 301         ret = jvmti->GetMethodName(stack_buffer[i].method, &mname, &signature, NULL);
 302         if (ret != JVMTI_ERROR_NONE) {
 303             printf("Error: GetMethodName %d  \n", ret);
 304             iGlobalStatus = 2;
 305             return;
 306         }
 307 
 308         debug_printf("[%d]  %s::%s(%s) at %lld \n",i,clname, mname, signature, stack_buffer[i].location);
 309 
 310 
 311     }
 312 
 313 
 314     ret = jvmti->Deallocate((unsigned char *) stack_buffer);
 315     if (ret != JVMTI_ERROR_NONE) {
 316         printf("Error: Deallocate failed with  %d \n", ret);
 317         iGlobalStatus = 2;
 318     }
 319 
 320 
 321 }
 322 
 323 JNIEXPORT void JNICALL
 324 Java_nsk_jvmti_unit_StackTrace_JvmtiTest_SaveThreadInfo(JNIEnv * env, jclass cls, jobject oobj) {
 325 
 326 }
 327 
 328 }