1 /* 2 * Copyright (c) 2004, 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 <stdlib.h> 25 #include <string.h> 26 #include "jni_tools.h" 27 #include "agent_common.h" 28 #include "jvmti_tools.h" 29 30 #define PASSED 0 31 #define STATUS_FAILED 2 32 33 extern "C" { 34 35 /* ========================================================================== */ 36 37 /* scaffold objects */ 38 static jlong timeout = 0; 39 40 /* test objects */ 41 static jthread thread = NULL; 42 43 /* event counts */ 44 static int MethodExitEventsCount = 0; 45 46 /* ========================================================================== */ 47 48 /** callback functions **/ 49 50 static void JNICALL 51 MethodExit(jvmtiEnv *jvmti_env, JNIEnv *jni_env, 52 jthread thread, jmethodID method, 53 jboolean was_poped_by_exception, jvalue return_value) { 54 char *name = NULL; 55 char *signature = NULL; 56 57 MethodExitEventsCount++; 58 if (!NSK_JVMTI_VERIFY(jvmti_env->GetMethodName(method, &name, &signature, NULL))) { 59 nsk_jvmti_setFailStatus(); 60 return; 61 } 62 NSK_DISPLAY2("MethodExit event: %s%s\n", name, signature); 63 if (name != NULL) 64 jvmti_env->Deallocate((unsigned char*)name); 65 if (signature != NULL) 66 jvmti_env->Deallocate((unsigned char*)signature); 67 } 68 69 /* ========================================================================== */ 70 71 static int prepare(jvmtiEnv* jvmti, JNIEnv* jni) { 72 const char* THREAD_NAME = "Debuggee Thread"; 73 jvmtiThreadInfo info; 74 jthread *threads = NULL; 75 jint threads_count = 0; 76 int i; 77 78 NSK_DISPLAY0("Prepare: find tested thread\n"); 79 80 /* get all live threads */ 81 if (!NSK_JVMTI_VERIFY(jvmti->GetAllThreads(&threads_count, &threads))) 82 return NSK_FALSE; 83 84 if (!NSK_VERIFY(threads_count > 0 && threads != NULL)) 85 return NSK_FALSE; 86 87 /* find tested thread */ 88 for (i = 0; i < threads_count; i++) { 89 if (!NSK_VERIFY(threads[i] != NULL)) 90 return NSK_FALSE; 91 92 /* get thread information */ 93 if (!NSK_JVMTI_VERIFY(jvmti->GetThreadInfo(threads[i], &info))) 94 return NSK_FALSE; 95 96 NSK_DISPLAY3(" thread #%d (%s): %p\n", i, info.name, threads[i]); 97 98 /* find by name */ 99 if (info.name != NULL && (strcmp(info.name, THREAD_NAME) == 0)) { 100 thread = threads[i]; 101 } 102 } 103 104 if (!NSK_JNI_VERIFY(jni, (thread = jni->NewGlobalRef(thread)) != NULL)) 105 return NSK_FALSE; 106 107 /* deallocate threads list */ 108 if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)threads))) 109 return NSK_FALSE; 110 111 return NSK_TRUE; 112 } 113 114 /* ========================================================================== */ 115 116 /** Agent algorithm. */ 117 static void JNICALL 118 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { 119 120 if (!nsk_jvmti_waitForSync(timeout)) 121 return; 122 123 if (!prepare(jvmti, jni)) { 124 nsk_jvmti_setFailStatus(); 125 return; 126 } 127 128 if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_METHOD_EXIT, thread))) 129 nsk_jvmti_setFailStatus(); 130 131 /* resume debugee and wait for sync */ 132 if (!nsk_jvmti_resumeSync()) 133 return; 134 if (!nsk_jvmti_waitForSync(timeout)) 135 return; 136 137 NSK_DISPLAY1("MethodExit events received: %d\n", 138 MethodExitEventsCount); 139 if (!NSK_VERIFY(MethodExitEventsCount != 0)) 140 nsk_jvmti_setFailStatus(); 141 142 NSK_TRACE(jni->DeleteGlobalRef(thread)); 143 144 if (!nsk_jvmti_resumeSync()) 145 return; 146 } 147 148 /* ========================================================================== */ 149 150 /** Agent library initialization. */ 151 #ifdef STATIC_BUILD 152 JNIEXPORT jint JNICALL Agent_OnLoad_ma10t003(JavaVM *jvm, char *options, void *reserved) { 153 return Agent_Initialize(jvm, options, reserved); 154 } 155 JNIEXPORT jint JNICALL Agent_OnAttach_ma10t003(JavaVM *jvm, char *options, void *reserved) { 156 return Agent_Initialize(jvm, options, reserved); 157 } 158 JNIEXPORT jint JNI_OnLoad_ma10t003(JavaVM *jvm, char *options, void *reserved) { 159 return JNI_VERSION_1_8; 160 } 161 #endif 162 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 163 jvmtiEnv* jvmti = NULL; 164 jvmtiCapabilities caps; 165 jvmtiEventCallbacks callbacks; 166 167 NSK_DISPLAY0("Agent_OnLoad\n"); 168 169 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 170 return JNI_ERR; 171 172 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 173 174 if (!NSK_VERIFY((jvmti = 175 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 176 return JNI_ERR; 177 178 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 179 return JNI_ERR; 180 181 memset(&caps, 0, sizeof(caps)); 182 caps.can_generate_method_exit_events = 1; 183 if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) { 184 return JNI_ERR; 185 } 186 187 memset(&callbacks, 0, sizeof(callbacks)); 188 callbacks.MethodExit = &MethodExit; 189 if (!NSK_VERIFY(nsk_jvmti_init_MA(&callbacks))) 190 return JNI_ERR; 191 192 return JNI_OK; 193 } 194 195 /* ========================================================================== */ 196 197 }