1 /* 2 * Copyright (c) 2007, 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 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <jni.h> 27 #include <jvmti.h> 28 #include <aod.h> 29 #include <jvmti_aod.h> 30 31 extern "C" { 32 33 /* 34 * Expected agent work scenario: 35 * - during initialization agent enables ThreadStart events 36 * - target application starts thread 37 * - agent receives ThreadStart event for this thread and tries to call GetThreadState for 38 * all VM threads, then finishes work 39 */ 40 41 #define STARTED_TEST_THREAD_NAME "attach042-TestThread" 42 43 static Options* options = NULL; 44 static const char* agentName; 45 46 void JNICALL threadStartHandler(jvmtiEnv *jvmti, 47 JNIEnv* jni, 48 jthread thread) { 49 char startedThreadName[MAX_STRING_LENGTH]; 50 51 if(!nsk_jvmti_aod_getThreadName(jvmti, thread, startedThreadName)) { 52 nsk_jvmti_aod_disableEventAndFinish(agentName, JVMTI_EVENT_THREAD_START, 0, jvmti, jni); 53 return; 54 } 55 56 NSK_DISPLAY2("%s: ThreadStart event was received for thread '%s'\n", agentName, startedThreadName); 57 58 if (!strcmp(startedThreadName, STARTED_TEST_THREAD_NAME)) { 59 int success = 1; 60 jint threadsCount = 0; 61 jthread* threads = NULL; 62 int i; 63 int startedThreadWasFound = 0; 64 65 if(!NSK_JVMTI_VERIFY(jvmti->GetAllThreads(&threadsCount, &threads))) { 66 NSK_COMPLAIN1("%s: failed to get all threads\n", agentName); 67 nsk_jvmti_aod_disableEventAndFinish(agentName, JVMTI_EVENT_THREAD_START, 0, jvmti, jni); 68 return; 69 } 70 71 NSK_DISPLAY1("%s: displaying threads status:\n", agentName); 72 73 for (i = 0; i < threadsCount; i++) { 74 jint threadState; 75 char threadName[MAX_STRING_LENGTH]; 76 77 if (!nsk_jvmti_aod_getThreadName(jvmti, threads[i], threadName)) { 78 NSK_COMPLAIN1("%s: failed to get thread name\n", agentName); 79 nsk_jvmti_aod_deallocate(jvmti, (unsigned char*)threads); 80 nsk_jvmti_aod_disableEventAndFinish(agentName, JVMTI_EVENT_THREAD_START, 0, jvmti, jni); 81 return; 82 } 83 84 if (!strcmp(threadName, startedThreadName)) { 85 startedThreadWasFound = 1; 86 } 87 88 if (!NSK_JVMTI_VERIFY(jvmti->GetThreadState(threads[i], &threadState))) { 89 NSK_COMPLAIN2("%s: failed to get status of thread '%s'\n", agentName, threadName); 90 nsk_jvmti_aod_deallocate(jvmti, (unsigned char*)threads); 91 nsk_jvmti_aod_disableEventAndFinish(agentName, JVMTI_EVENT_THREAD_START, 0, jvmti, jni); 92 return; 93 } 94 95 NSK_DISPLAY3("%s: status of '%s': %s\n", agentName, threadName, TranslateState(threadState)); 96 } 97 98 nsk_jvmti_aod_deallocate(jvmti, (unsigned char*)threads); 99 100 if (!startedThreadWasFound) { 101 NSK_COMPLAIN2("%s: thread '%s' wasn't returned by GetAllThreads\n", agentName, startedThreadName); 102 success = 0; 103 } 104 105 nsk_jvmti_aod_disableEventAndFinish(agentName, JVMTI_EVENT_THREAD_START, success, jvmti, jni); 106 } 107 } 108 109 #ifdef STATIC_BUILD 110 JNIEXPORT jint JNI_OnLoad_attach042Agent00(JavaVM *jvm, char *options, void *reserved) { 111 return JNI_VERSION_1_8; 112 } 113 #endif 114 115 JNIEXPORT jint JNICALL 116 #ifdef STATIC_BUILD 117 Agent_OnAttach_attach042Agent00(JavaVM *vm, char *optionsString, void *reserved) 118 #else 119 Agent_OnAttach(JavaVM *vm, char *optionsString, void *reserved) 120 #endif 121 { 122 jvmtiEventCallbacks eventCallbacks; 123 jvmtiEnv* jvmti; 124 JNIEnv* jni; 125 126 if (!NSK_VERIFY((options = (Options*) nsk_aod_createOptions(optionsString)) != NULL)) 127 return JNI_ERR; 128 129 agentName = nsk_aod_getOptionValue(options, NSK_AOD_AGENT_NAME_OPTION); 130 131 if ((jni = (JNIEnv*) nsk_aod_createJNIEnv(vm)) == NULL) 132 return JNI_ERR; 133 134 if (!NSK_VERIFY((jvmti = nsk_jvmti_createJVMTIEnv(vm, reserved)) != NULL)) 135 return JNI_ERR; 136 137 memset(&eventCallbacks,0, sizeof(eventCallbacks)); 138 eventCallbacks.ThreadStart = threadStartHandler; 139 if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&eventCallbacks, sizeof(eventCallbacks))) ) { 140 return JNI_ERR; 141 } 142 143 if (!(nsk_jvmti_aod_enableEvent(jvmti, JVMTI_EVENT_THREAD_START))) { 144 return JNI_ERR; 145 } 146 147 NSK_DISPLAY1("%s: initialization was done\n", agentName); 148 149 if (!NSK_VERIFY(nsk_aod_agentLoaded(jni, agentName))) 150 return JNI_ERR; 151 152 return JNI_OK; 153 } 154 155 }