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