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 24 #include <string.h> 25 #include <jvmti.h> 26 #include "agent_common.h" 27 #include "jni_tools.h" 28 #include "jvmti_tools.h" 29 #include "jvmti_FollowRefObjects.h" 30 31 extern "C" { 32 33 /* ============================================================================= */ 34 35 static jlong g_timeout = 0; 36 37 #define JAVA_LANG_STRING_CLASS_NAME "java/lang/String" 38 #define JAVA_IO_SERIALIZABLE_CLASS_NAME "java/io/Serializable" 39 #define JAVA_UTIL_CALENDAR_CLASS_NAME "java/util/Calendar" 40 41 static jobject g_jniGlobalRef = 0; 42 static jweak g_jniWeakGlobalRef = 0; 43 44 static jvmtiHeapCallbacks g_heapCallbacks; 45 46 /* ============================================================================= */ 47 48 jint JNICALL heapReferenceCallback( 49 jvmtiHeapReferenceKind reference_kind, 50 const jvmtiHeapReferenceInfo* reference_info, 51 jlong class_tag, 52 jlong referrer_class_tag, 53 jlong size, 54 jlong* tag_ptr, 55 jlong* referrer_tag_ptr, 56 jint length, 57 void* user_data) 58 { 59 CHECK_USER_DATA(user_data); 60 61 printHeapRefCallbackInfo(reference_kind, reference_info, class_tag, referrer_class_tag, size, tag_ptr, referrer_tag_ptr, length); 62 63 markTagVisited(DEREF(tag_ptr)); 64 markRefToVerify(DEREF(referrer_tag_ptr), DEREF(tag_ptr), reference_kind); 65 66 return JVMTI_VISIT_OBJECTS; 67 68 } /* heapReferenceCallback */ 69 70 71 jint JNICALL primitiveFieldCallback( 72 jvmtiHeapReferenceKind reference_kind, 73 const jvmtiHeapReferenceInfo* reference_info, 74 jlong class_tag, 75 jlong* tag_ptr, 76 jvalue value, 77 jvmtiPrimitiveType value_type, 78 void* user_data) 79 { 80 CHECK_USER_DATA(user_data); 81 82 printf(" primitiveFieldCallback: ref=%s," 83 " class_tag=%-3ld, tag=%-3ld, type=%c\n", 84 g_refKindStr[reference_kind], 85 (long) class_tag, 86 (long) DEREF(tag_ptr), 87 (int ) value_type); 88 89 fflush(0); 90 91 markTagVisited(DEREF(tag_ptr)); 92 93 return JVMTI_VISIT_OBJECTS; 94 95 } /* primitiveFieldCallback */ 96 97 98 jint JNICALL arrayPrimitiveValueCallback( 99 jlong class_tag, 100 jlong size, 101 jlong* tag_ptr, 102 jint element_count, 103 jvmtiPrimitiveType element_type, 104 const void* elements, 105 void* user_data) 106 { 107 CHECK_USER_DATA(user_data); 108 109 printf(" arrayPrimitiveValueCallback: class_tag=%-3ld, tag=%-3ld, len=%d, type=%c\n", 110 (long) class_tag, 111 (long) DEREF(tag_ptr), 112 (int ) element_count, 113 (int ) element_type); 114 fflush(0); 115 116 markTagVisited(DEREF(tag_ptr)); 117 118 return JVMTI_VISIT_OBJECTS; 119 120 } /* arrayPrimitiveValueCallback */ 121 122 123 jint JNICALL stringPrimitiveValueCallback( 124 jlong class_tag, 125 jlong size, 126 jlong* tag_ptr, 127 const jchar* value, 128 jint value_length, 129 void* user_data) 130 { 131 printf("stringPrimitiveValueCallback: class_tag=%-3ld, tag=%-3ld, len=%d\n", 132 (long) class_tag, 133 (long) DEREF(tag_ptr), 134 (int ) value_length); 135 fflush(0); 136 137 markTagVisited(DEREF(tag_ptr)); 138 139 return JVMTI_VISIT_OBJECTS; 140 141 } /* stringPrimitiveValueCallback */ 142 143 /* ============================================================================= */ 144 145 static void createGlobalRefs(JNIEnv * jni) 146 { 147 jclass klass; 148 149 if ( ! NSK_JNI_VERIFY(jni, (klass = jni->FindClass(JAVA_LANG_STRING_CLASS_NAME)) != NULL) ) { 150 nsk_jvmti_setFailStatus(); 151 return; 152 } 153 154 if ( ! NSK_JNI_VERIFY(jni, (g_jniGlobalRef = jni->NewGlobalRef(klass)) != NULL) ) { 155 nsk_jvmti_setFailStatus(); 156 } 157 158 if ( ! NSK_JNI_VERIFY(jni, (g_jniWeakGlobalRef = jni->NewWeakGlobalRef(klass)) != NULL) ) { 159 nsk_jvmti_setFailStatus(); 160 } 161 162 } /* createGlobalRefs */ 163 164 /** Agent algorithm. */ 165 166 static void JNICALL agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) 167 { 168 jvmtiError retCode; 169 170 printf(">>> Sync with Java code\n"); 171 fflush(0); 172 173 if (!NSK_VERIFY(nsk_jvmti_waitForSync(g_timeout))) { 174 return; 175 } 176 177 printf(">>> Create JNI global references\n"); 178 fflush(0); 179 180 createGlobalRefs(jni); 181 182 retCode = jvmti->FollowReferences((jint) 0, /* heap filter */ 183 NULL, /* class */ 184 NULL, /* inital object */ 185 &g_heapCallbacks, 186 (const void *) &g_fakeUserData); 187 188 if ( ! NSK_VERIFY(retCode == JVMTI_ERROR_NONE) ) { 189 nsk_jvmti_setFailStatus(); 190 } 191 192 checkThatAllTagsVisited(); 193 194 printf(">>> Let debugee to finish\n"); 195 fflush(0); 196 197 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) { 198 return; 199 } 200 201 } /* agentProc */ 202 203 204 /* ============================================================================= */ 205 206 /** Agent library initialization. */ 207 208 #ifdef STATIC_BUILD 209 JNIEXPORT jint JNICALL Agent_OnLoad_followref004(JavaVM *jvm, char *options, void *reserved) { 210 return Agent_Initialize(jvm, options, reserved); 211 } 212 JNIEXPORT jint JNICALL Agent_OnAttach_followref004(JavaVM *jvm, char *options, void *reserved) { 213 return Agent_Initialize(jvm, options, reserved); 214 } 215 JNIEXPORT jint JNI_OnLoad_followref004(JavaVM *jvm, char *options, void *reserved) { 216 return JNI_VERSION_1_8; 217 } 218 #endif 219 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) 220 { 221 jvmtiEnv* jvmti = NULL; 222 223 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) { 224 return JNI_ERR; 225 } 226 227 g_timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 228 229 if (!NSK_VERIFY((jvmti = nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) { 230 return JNI_ERR; 231 } 232 233 /* Setting Heap Callbacks */ 234 memset(&g_heapCallbacks, 0, sizeof(g_heapCallbacks)); 235 g_heapCallbacks.heap_iteration_callback = NULL; 236 g_heapCallbacks.heap_reference_callback = heapReferenceCallback; 237 g_heapCallbacks.primitive_field_callback = primitiveFieldCallback; 238 g_heapCallbacks.array_primitive_value_callback = arrayPrimitiveValueCallback; 239 g_heapCallbacks.string_primitive_value_callback = stringPrimitiveValueCallback; 240 241 jvmti_FollowRefObject_init(); 242 243 { 244 jvmtiCapabilities caps; 245 246 memset(&caps, 0, sizeof(caps)); 247 caps.can_tag_objects = 1; 248 if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) { 249 return JNI_ERR; 250 } 251 } 252 253 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) { 254 return JNI_ERR; 255 } 256 257 return JNI_OK; 258 259 } /* Agent_OnLoad */ 260 261 262 /* ============================================================================= */ 263 264 }