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 <string.h> 25 #include "jvmti.h" 26 #include "agent_common.h" 27 #include "jni_tools.h" 28 #include "jvmti_tools.h" 29 30 extern "C" { 31 32 33 /* ============================================================================= */ 34 35 /* constant names */ 36 #define DEBUGEE_CLASS_NAME "nsk/jvmti/scenarios/sampling/SP01/sp01t001" 37 #define THREAD_CLASS_NAME "nsk/jvmti/scenarios/sampling/SP01/sp01t001Thread" 38 #define THREADS_FIELD_NAME "threads" 39 #define THREADS_FIELD_SIG "[L" THREAD_CLASS_NAME ";" 40 41 /* scaffold objects */ 42 static JNIEnv* jni = NULL; 43 static jvmtiEnv *jvmti = NULL; 44 static jlong timeout = 0; 45 46 /* number of tested threads */ 47 #define THREADS_COUNT 2 48 49 /* names of tested threads */ 50 static const char* threadsName[THREADS_COUNT] = { 51 "NotStarted", 52 "Finished" 53 }; 54 55 #define JVMTI_THREAD_STATE_NOT_STARTED 0 56 /* expected states of tested threads */ 57 static jint threadsState[THREADS_COUNT] = { 58 JVMTI_THREAD_STATE_NOT_STARTED, /* JVMTI_THREAD_STATUS_NOT_STARTED */ 59 JVMTI_THREAD_STATE_TERMINATED /* JVMTI_THREAD_STATUS_ZOMBIE */ 60 }; 61 62 /* references to tested threads */ 63 static jthread threadsList[THREADS_COUNT]; 64 65 /* ============================================================================= */ 66 67 /* testcase(s) */ 68 static int prepare(); 69 static int checkThreads(const char* kind); 70 static int clean(); 71 72 /* ============================================================================= */ 73 74 /** Agent algorithm. */ 75 static void JNICALL 76 agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) { 77 jni = agentJNI; 78 79 /* wait for initial sync */ 80 if (!nsk_jvmti_waitForSync(timeout)) 81 return; 82 83 /* perform testcase(s) */ 84 { 85 /* obtain threads list */ 86 if (!prepare()) { 87 nsk_jvmti_setFailStatus(); 88 return; 89 } 90 91 /* testcase #1: check not alive threads */ 92 NSK_DISPLAY0("Testcase #1: check state of not alive threads\n"); 93 if (!checkThreads("not alive")) 94 return; 95 96 /* clean threads references */ 97 if (!clean()) { 98 nsk_jvmti_setFailStatus(); 99 return; 100 } 101 } 102 103 /* resume debugee after last sync */ 104 if (!nsk_jvmti_resumeSync()) 105 return; 106 } 107 108 /* ============================================================================= */ 109 110 /** 111 * Prepare data: 112 * - get threads array from static field 113 * - get each thread from array 114 * - make global refs 115 */ 116 static int prepare() { 117 jclass debugeeClass = NULL; 118 jfieldID threadsFieldID = NULL; 119 jobjectArray threadsArray = NULL; 120 jsize threadsArrayLength = 0; 121 jsize i; 122 123 /* find debugee class */ 124 if (!NSK_JNI_VERIFY(jni, (debugeeClass = 125 NSK_CPP_STUB2(FindClass, jni, DEBUGEE_CLASS_NAME)) != NULL)) 126 return NSK_FALSE; 127 128 /* find static field with threads array */ 129 if (!NSK_JNI_VERIFY(jni, (threadsFieldID = 130 NSK_CPP_STUB4(GetStaticFieldID, jni, debugeeClass, 131 THREADS_FIELD_NAME, THREADS_FIELD_SIG)) != NULL)) 132 return NSK_FALSE; 133 134 /* get threads array from static field */ 135 if (!NSK_JNI_VERIFY(jni, (threadsArray = (jobjectArray) 136 NSK_CPP_STUB3(GetStaticObjectField, jni, debugeeClass, threadsFieldID)) != NULL)) 137 return NSK_FALSE; 138 139 /* check array length */ 140 if (!NSK_JNI_VERIFY(jni, (threadsArrayLength = 141 NSK_CPP_STUB2(GetArrayLength, jni, threadsArray)) == THREADS_COUNT)) 142 return NSK_FALSE; 143 144 /* get each thread from array */ 145 for (i = 0; i < THREADS_COUNT; i++) { 146 if (!NSK_JNI_VERIFY(jni, (threadsList[i] = (jthread) 147 NSK_CPP_STUB3(GetObjectArrayElement, jni, threadsArray, i)) != NULL)) 148 return NSK_FALSE; 149 } 150 151 /* make global references to threads */ 152 for (i = 0; i < THREADS_COUNT; i++) { 153 if (!NSK_JNI_VERIFY(jni, (threadsList[i] = (jthread) 154 NSK_CPP_STUB2(NewGlobalRef, jni, threadsList[i])) != NULL)) 155 return NSK_FALSE; 156 } 157 158 return NSK_TRUE; 159 } 160 161 /** 162 * Testcase: check threads state for given suspension 163 * 164 * Returns NSK_TRUE if test may continue; or NSK_FALSE for test break. 165 */ 166 static int checkThreads(const char* kind) { 167 int i; 168 169 /* check each thread */ 170 for (i = 0; i < THREADS_COUNT; i++) { 171 jthread thread = threadsList[i]; 172 jint state = JVMTI_THREAD_STATE_NOT_STARTED; 173 174 NSK_DISPLAY2(" thread #%d (%s):\n", i, threadsName[i]); 175 176 /* get thread state */ 177 if (!NSK_JVMTI_VERIFY( 178 NSK_CPP_STUB3(GetThreadState, jvmti, threadsList[i], &state))) { 179 nsk_jvmti_setFailStatus(); 180 return NSK_TRUE; 181 } 182 183 /* display thread state */ 184 NSK_DISPLAY2(" state=%s (%d)\n", 185 TranslateState(state), (int)state); 186 187 /* check thread state */ 188 if ((state & threadsState[i]) == 0) { 189 if (state == JVMTI_THREAD_STATE_NOT_STARTED) { 190 NSK_DISPLAY1("state of thread #%d is NOT_STARTED\n", kind); 191 } else { 192 NSK_COMPLAIN7("Unexpected state of %s thread #%d (%s):\n" 193 "# got: %s (%d), expected: %s (%d)\n", 194 kind, i, threadsName[i], 195 TranslateState(state), (int)state, 196 TranslateState(threadsState[i]), (int)threadsState[i]); 197 nsk_jvmti_setFailStatus(); 198 } 199 } 200 201 /* check SUSPENDED state flag */ 202 if (state & JVMTI_THREAD_STATE_SUSPENDED) { 203 NSK_COMPLAIN3("Unexpected SUSPENDED state flag for %s thread #%d: %d\n", 204 kind, i, (int)state); 205 nsk_jvmti_setFailStatus(); 206 } 207 208 /* check INTERRUPTED state flag */ 209 if (state & JVMTI_THREAD_STATE_INTERRUPTED) { 210 NSK_COMPLAIN3("Unexpected INTERRUPTED state flag for %s thread #%d: %d\n", 211 kind, i, (int)state); 212 nsk_jvmti_setFailStatus(); 213 } 214 215 /* check NATIVE state flag */ 216 if (state & JVMTI_THREAD_STATE_IN_NATIVE) { 217 NSK_COMPLAIN3("Unexpected NATIVE state flag for %s thread #%d: %d\n", 218 kind, i, (int)state); 219 nsk_jvmti_setFailStatus(); 220 } 221 } 222 223 /* test may continue */ 224 return NSK_TRUE; 225 } 226 227 /** 228 * Clean data: 229 * - dispose global references to tested threads 230 */ 231 static int clean() { 232 int i; 233 234 /* dispose global references to threads */ 235 for (i = 0; i < THREADS_COUNT; i++) { 236 NSK_TRACE(NSK_CPP_STUB2(DeleteGlobalRef, jni, threadsList[i])); 237 } 238 239 return NSK_TRUE; 240 } 241 242 /* ============================================================================= */ 243 244 /** Agent library initialization. */ 245 #ifdef STATIC_BUILD 246 JNIEXPORT jint JNICALL Agent_OnLoad_sp01t001(JavaVM *jvm, char *options, void *reserved) { 247 return Agent_Initialize(jvm, options, reserved); 248 } 249 JNIEXPORT jint JNICALL Agent_OnAttach_sp01t001(JavaVM *jvm, char *options, void *reserved) { 250 return Agent_Initialize(jvm, options, reserved); 251 } 252 JNIEXPORT jint JNI_OnLoad_sp01t001(JavaVM *jvm, char *options, void *reserved) { 253 return JNI_VERSION_1_8; 254 } 255 #endif 256 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 257 258 /* init framework and parse options */ 259 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 260 return JNI_ERR; 261 262 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 263 264 /* create JVMTI environment */ 265 if (!NSK_VERIFY((jvmti = 266 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 267 return JNI_ERR; 268 269 /* register agent proc and arg */ 270 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 271 return JNI_ERR; 272 273 return JNI_OK; 274 } 275 276 /* ============================================================================= */ 277 278 }