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 <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 static JNIEnv *jni = NULL; 33 static jvmtiEnv *jvmti = NULL; 34 static jvmtiCapabilities caps; 35 static jlong timeout = 0; 36 37 /* ============================================================================= */ 38 39 40 static volatile long objectDescCount = 0; 41 static volatile int callbackAborted = 0; 42 static volatile int numberOfDeallocatedFromCallbacksDescriptors = 0; 43 44 typedef struct ObjectDescStruct { 45 struct ObjectDescStruct *next; 46 } ObjectDesc; 47 48 static ObjectDesc* volatile objectDescList; 49 static ObjectDesc* *objectDescArr; 50 static unsigned char* deallocatedFlagsArr; 51 52 53 /* ============================================================================= */ 54 55 56 /** heapRootCallback for first heap iteration. */ 57 jvmtiIterationControl JNICALL 58 heapObjectCallbackForFirstIteration(jlong class_tag, 59 jlong size, 60 jlong* tag_ptr, 61 void* user_data) { 62 ObjectDesc *objectDescBuf; 63 64 /* set tag */ 65 *tag_ptr = (jlong)++objectDescCount; 66 67 /* Allocate memory for next list element*/ 68 if (!NSK_JVMTI_VERIFY(jvmti->Allocate((sizeof(ObjectDesc)), (unsigned char**)&objectDescBuf))) { 69 nsk_jvmti_setFailStatus(); 70 callbackAborted = 1; 71 NSK_COMPLAIN0("heapObjectCallbackForFirstIteration: Allocation failed. Iteration aborted.\n"); 72 return JVMTI_ITERATION_ABORT; 73 } 74 objectDescBuf->next = objectDescList; 75 objectDescList = objectDescBuf; 76 77 return JVMTI_ITERATION_CONTINUE; 78 } 79 80 /** heapRootCallback for second heap iterator. */ 81 jvmtiIterationControl JNICALL 82 heapObjectCallbackForSecondIteration(jlong class_tag, 83 jlong size, 84 jlong* tag_ptr, 85 void* user_data) { 86 87 long ind = (long)((*tag_ptr) - 1); 88 89 if (ind < 0 || ind > objectDescCount ) { 90 NSK_COMPLAIN1("heapObjectCallbackForSecondIteration: invalid object tag value: %d\n", (long)*tag_ptr); 91 nsk_jvmti_setFailStatus(); 92 callbackAborted = 1; 93 return JVMTI_ITERATION_ABORT; 94 } 95 96 /* Deallocate memory of list element*/ 97 if (!NSK_JVMTI_VERIFY( 98 jvmti->Deallocate((unsigned char*)objectDescArr[ind]))) { 99 nsk_jvmti_setFailStatus(); 100 callbackAborted = 1; 101 NSK_COMPLAIN0("heapObjectCallbackForSecondIteration: Deallocation failed. Iteration aborted.\n"); 102 return JVMTI_ITERATION_ABORT; 103 } 104 105 numberOfDeallocatedFromCallbacksDescriptors++; 106 deallocatedFlagsArr[ind] = 1; 107 108 /* unset tag */ 109 *tag_ptr = 0; 110 111 return JVMTI_ITERATION_CONTINUE; 112 } 113 114 /* ============================================================================= */ 115 116 /** Agent algorithm. */ 117 static void JNICALL 118 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { 119 long ind; 120 ObjectDesc *objectDesc; 121 int fakeUserData = 0; 122 123 NSK_DISPLAY0("Wait for debugee start\n"); 124 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) 125 return; 126 127 { 128 do { 129 objectDescList = NULL; 130 131 NSK_DISPLAY0("Calling IterateOverHeap with filter JVMTI_HEAP_OBJECT_UNTAGGED\n"); 132 { 133 if (!NSK_JVMTI_VERIFY( 134 jvmti->IterateOverHeap(JVMTI_HEAP_OBJECT_UNTAGGED, heapObjectCallbackForFirstIteration, &fakeUserData))) { 135 nsk_jvmti_setFailStatus(); 136 break; 137 } 138 } 139 if (callbackAborted) break; 140 141 if (objectDescCount == 0) { 142 NSK_COMPLAIN0("First IterateOverHeap call had not visited any object\n"); 143 nsk_jvmti_setFailStatus(); 144 break; 145 } else { 146 NSK_DISPLAY1("Number of objects first IterateOverHeap visited: %d\n", objectDescCount); 147 } 148 149 /* Allocate memory for array to save pointers to ObjectDescList elements */ 150 if (!NSK_JVMTI_VERIFY(jvmti->Allocate((objectDescCount * sizeof(ObjectDesc*)), (unsigned char**)&objectDescArr))) { 151 nsk_jvmti_setFailStatus(); 152 break; 153 } 154 155 /* Allocate memory for flags array and fill with false values */ 156 if (!NSK_JVMTI_VERIFY(jvmti->Allocate((objectDescCount * sizeof(unsigned char)), &deallocatedFlagsArr))) { 157 nsk_jvmti_setFailStatus(); 158 break; 159 } 160 161 for (ind = 0; ind < objectDescCount; ind++) { 162 deallocatedFlagsArr[ind] = 0; 163 } 164 165 /* Save all pointers to ObjectDescList elements in objectDescArr */ 166 objectDesc = objectDescList; 167 for (ind = 0; ind < objectDescCount; ind++) { 168 objectDescArr[ind] = objectDesc; 169 objectDesc = objectDesc->next; 170 } 171 172 /* Verify objectDescCount and objectDescList length in agreement */ 173 if (!NSK_VERIFY(objectDesc == NULL)) { 174 nsk_jvmti_setFailStatus(); 175 break; 176 } 177 178 NSK_DISPLAY0("Calling IterateOverHeap with filter JVMTI_HEAP_OBJECT_TAGGED\n"); 179 { 180 if (!NSK_JVMTI_VERIFY( 181 jvmti->IterateOverHeap(JVMTI_HEAP_OBJECT_TAGGED, heapObjectCallbackForSecondIteration, &fakeUserData))) { 182 nsk_jvmti_setFailStatus(); 183 } 184 } 185 186 if (numberOfDeallocatedFromCallbacksDescriptors == 0) { 187 NSK_COMPLAIN1("Deallocate func. hasn't been called from IterateOverHeap'callback. " 188 "numberOfDeallocatedFromCallbacksDescriptors = %d\n", numberOfDeallocatedFromCallbacksDescriptors); 189 nsk_jvmti_setFailStatus(); 190 } 191 192 for (ind = 0; ind < objectDescCount; ind++) { 193 if (!deallocatedFlagsArr[ind]) { 194 if (!NSK_JVMTI_VERIFY( 195 jvmti->Deallocate((unsigned char*)objectDescArr[ind]))) { 196 NSK_COMPLAIN1("Unable to deallocate descriptor. Index = %d \n", ind); 197 nsk_jvmti_setFailStatus(); 198 return; 199 } 200 } 201 } 202 203 if (!NSK_JVMTI_VERIFY( 204 jvmti->Deallocate((unsigned char*)objectDescArr))) { 205 nsk_jvmti_setFailStatus(); 206 } 207 208 if (!NSK_JVMTI_VERIFY( 209 jvmti->Deallocate((unsigned char*)deallocatedFlagsArr))) { 210 nsk_jvmti_setFailStatus(); 211 } 212 213 } while (0); 214 } 215 216 NSK_DISPLAY0("Let debugee to finish\n"); 217 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) 218 return; 219 } 220 221 /* ============================================================================= */ 222 223 /* ============================================================================= */ 224 225 /** Agent library initialization. */ 226 #ifdef STATIC_BUILD 227 JNIEXPORT jint JNICALL Agent_OnLoad_iterheap004(JavaVM *jvm, char *options, void *reserved) { 228 return Agent_Initialize(jvm, options, reserved); 229 } 230 JNIEXPORT jint JNICALL Agent_OnAttach_iterheap004(JavaVM *jvm, char *options, void *reserved) { 231 return Agent_Initialize(jvm, options, reserved); 232 } 233 JNIEXPORT jint JNI_OnLoad_iterheap004(JavaVM *jvm, char *options, void *reserved) { 234 return JNI_VERSION_1_8; 235 } 236 #endif 237 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 238 239 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 240 return JNI_ERR; 241 242 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 243 244 if (!NSK_VERIFY((jvmti = 245 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 246 return JNI_ERR; 247 248 memset(&caps, 0, sizeof(caps)); 249 caps.can_tag_objects = 1; 250 if (!NSK_JVMTI_VERIFY( 251 jvmti->AddCapabilities(&caps))) { 252 return JNI_ERR; 253 } 254 255 if (!NSK_JVMTI_VERIFY(jvmti->GetCapabilities(&caps))) 256 return JNI_ERR; 257 258 if (!caps.can_tag_objects) 259 NSK_DISPLAY0("Warning: tagging objects is not available\n"); 260 261 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 262 return JNI_ERR; 263 264 return JNI_OK; 265 } 266 267 /* ============================================================================= */ 268 269 }