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 <stdio.h> 25 #include <string.h> 26 #include <jvmti.h> 27 #include "agent_common.h" 28 29 #include "nsk_tools.h" 30 #include "jni_tools.h" 31 #include "JVMTITools.h" 32 #include "jvmti_tools.h" 33 34 extern "C" { 35 36 #define EXP_OBJ_NUMBER 1 37 38 static JNIEnv *jni = NULL; 39 static jvmtiEnv *jvmti = NULL; 40 static jvmtiEventCallbacks callbacks; 41 static jvmtiCapabilities caps; 42 43 static jlong timeout = 0; 44 static jlong threadTag = 1; 45 static int rootThreadCount = 0; 46 static int rootJNIGlobalCount = 0; 47 static int rootJNILocalCount = 0; 48 static const char* DEBUGEE_SIGNATURE = "Lnsk/jvmti/scenarios/allocation/AP06/ap06t001;"; 49 static const char* THREAD_CLS_SIGNATURE = "Lnsk/jvmti/scenarios/allocation/AP06/ap06t001Thread;"; 50 51 /* jvmtiHeapRootCallback */ 52 jvmtiIterationControl JNICALL 53 heapRootCallback(jvmtiHeapRootKind root_kind, 54 jlong class_tag, 55 jlong size, 56 jlong* tag_ptr, 57 void* user_data) { 58 59 if (*tag_ptr == threadTag) { 60 NSK_DISPLAY1("heapRootCallback: root kind=%s\n", TranslateRootKind(root_kind)); 61 switch (root_kind) { 62 case JVMTI_HEAP_ROOT_THREAD: 63 rootThreadCount++; 64 break; 65 case JVMTI_HEAP_ROOT_JNI_GLOBAL: 66 rootJNIGlobalCount++; 67 break; 68 default: 69 nsk_jvmti_setFailStatus(); 70 NSK_COMPLAIN1("heapRootCallback: unexpected root kind=%s\n", TranslateRootKind(root_kind)); 71 } 72 } 73 return JVMTI_ITERATION_CONTINUE; 74 } 75 76 /* jvmtiStackReferenceCallback */ 77 jvmtiIterationControl JNICALL 78 stackReferenceCallback(jvmtiHeapRootKind root_kind, 79 jlong class_tag, 80 jlong size, 81 jlong* tag_ptr, 82 jlong thread_tag, 83 jint depth, 84 jmethodID method, 85 jint slot, 86 void* user_data) { 87 88 if (*tag_ptr == threadTag) { 89 NSK_DISPLAY4("stackReferenceCallback: root kind=%s, " 90 "method=%p, depth=%d, slot=%d\n", TranslateRootKind(root_kind), (void *)method, (int)depth, (int)slot); 91 switch (root_kind) { 92 case JVMTI_HEAP_ROOT_STACK_LOCAL: 93 /* it's OK */ 94 break; 95 96 case JVMTI_HEAP_ROOT_JNI_LOCAL: 97 rootJNILocalCount++; 98 break; 99 default: 100 nsk_jvmti_setFailStatus(); 101 NSK_COMPLAIN1("stackReferenceCallback: unexpected root kind: %s\n\n", TranslateRootKind(root_kind)); 102 } 103 } 104 return JVMTI_ITERATION_CONTINUE; 105 } 106 107 108 /* jvmtiObjectReferenceCallback */ 109 jvmtiIterationControl JNICALL 110 objectReferenceCallback(jvmtiObjectReferenceKind reference_kind, 111 jlong class_tag, 112 jlong size, 113 jlong* tag_ptr, 114 jlong referrer_tag, 115 jint referrer_index, 116 void* user_data) { 117 118 return JVMTI_ITERATION_ABORT; 119 } 120 121 122 /************************/ 123 124 JNIEXPORT void JNICALL 125 Java_nsk_jvmti_scenarios_allocation_AP06_ap06t001Thread_setTag(JNIEnv* jni, jobject obj) { 126 127 if (!NSK_JVMTI_VERIFY(jvmti->SetTag(obj, threadTag))) { 128 nsk_jvmti_setFailStatus(); 129 } else { 130 NSK_DISPLAY0("setTag: the tag was set for checked thread."); 131 } 132 } 133 134 static void JNICALL 135 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { 136 137 jclass debugeeClass = NULL; 138 139 NSK_DISPLAY0("Wait for debugee start\n\n"); 140 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) 141 return; 142 143 do { 144 jthread localRefThread; 145 jthread globalRefThread; 146 jfieldID fid; 147 148 NSK_DISPLAY1("Find debugee class: %s\n", DEBUGEE_SIGNATURE); 149 debugeeClass = nsk_jvmti_classBySignature(DEBUGEE_SIGNATURE); 150 if (debugeeClass == NULL) { 151 nsk_jvmti_setFailStatus(); 152 break; 153 } 154 155 if (!NSK_JNI_VERIFY(jni, (fid = 156 jni->GetStaticFieldID(debugeeClass, "thread", THREAD_CLS_SIGNATURE)) != NULL)) { 157 nsk_jvmti_setFailStatus(); 158 break; 159 } 160 161 if (!NSK_JNI_VERIFY(jni, (localRefThread = 162 jni->GetStaticObjectField(debugeeClass, fid)) != NULL)) { 163 NSK_COMPLAIN0("GetStaticObjectField returned NULL for 'thread' field value\n\n"); 164 nsk_jvmti_setFailStatus(); 165 break; 166 } 167 168 if (!NSK_JNI_VERIFY(jni, (globalRefThread = jni->NewGlobalRef(localRefThread)) != NULL)) 169 return; 170 171 NSK_DISPLAY0("Calling IterateOverReachableObjects\n"); 172 if (!NSK_JVMTI_VERIFY(jvmti->IterateOverReachableObjects(heapRootCallback, 173 stackReferenceCallback, 174 objectReferenceCallback, 175 NULL /*user_data*/))) { 176 nsk_jvmti_setFailStatus(); 177 break; 178 } 179 180 if (rootJNILocalCount != 1) { 181 nsk_jvmti_setFailStatus(); 182 NSK_COMPLAIN1("JVMTI_HEAP_ROOT_JNI_LOCAL root kind was returned wrong %d times " 183 "while iteration with IterateOverReachableObjects.\n\n", rootJNILocalCount); 184 } 185 186 if (rootJNIGlobalCount != 1) { 187 nsk_jvmti_setFailStatus(); 188 NSK_COMPLAIN1("JVMTI_HEAP_ROOT_JNI_GLOBAL root kind was returned wrong %d times " 189 "while iteration with IterateOverReachableObjects.\n\n", rootJNIGlobalCount); 190 } 191 192 if (rootThreadCount != 1) { 193 nsk_jvmti_setFailStatus(); 194 NSK_COMPLAIN1("JVMTI_HEAP_ROOT_THREAD root kind was returned wrong %d times " 195 "while iteration with IterateOverReachableObjects.\n\n", rootThreadCount); 196 } 197 198 } while (0); 199 200 NSK_DISPLAY0("Let debugee to finish\n"); 201 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) 202 return; 203 } 204 205 #ifdef STATIC_BUILD 206 JNIEXPORT jint JNICALL Agent_OnLoad_ap06t001(JavaVM *jvm, char *options, void *reserved) { 207 return Agent_Initialize(jvm, options, reserved); 208 } 209 JNIEXPORT jint JNICALL Agent_OnAttach_ap06t001(JavaVM *jvm, char *options, void *reserved) { 210 return Agent_Initialize(jvm, options, reserved); 211 } 212 JNIEXPORT jint JNI_OnLoad_ap06t001(JavaVM *jvm, char *options, void *reserved) { 213 return JNI_VERSION_1_8; 214 } 215 #endif 216 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 217 /* init framework and parse options */ 218 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 219 return JNI_ERR; 220 221 /* create JVMTI environment */ 222 if (!NSK_VERIFY((jvmti = 223 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 224 return JNI_ERR; 225 226 memset(&caps, 0, sizeof(jvmtiCapabilities)); 227 caps.can_tag_objects = 1; 228 229 if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) 230 return JNI_ERR; 231 232 if (!NSK_JVMTI_VERIFY(jvmti->GetCapabilities(&caps))) 233 return JNI_ERR; 234 235 if (!caps.can_tag_objects) 236 NSK_DISPLAY0("Warning: tagging objects is not implemented\n"); 237 238 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 239 return JNI_ERR; 240 NSK_DISPLAY0("agentProc has been set\n\n"); 241 242 return JNI_OK; 243 } 244 245 }