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 42 /* ============================================================================= */ 43 44 static void verifyReturnCodes(JNIEnv* jni, jvmtiEnv* jvmti) 45 { 46 jvmtiError retCode; 47 jlong tag; 48 jvmtiHeapCallbacks emptyHeapCallbacks; 49 50 NSK_DISPLAY0("FollowReferences: Invalid class:"); 51 52 retCode = NSK_CPP_STUB6(FollowReferences, 53 jvmti, 54 (jint) 0, /* heap filter */ 55 (jclass) &g_wrongHeapCallbacks , /* invalid class, but valid memory address */ 56 NULL, /* inital object */ 57 &g_wrongHeapCallbacks, 58 (const void *) &g_fakeUserData); 59 60 if ( ! NSK_VERIFY(retCode == JVMTI_ERROR_INVALID_CLASS ) ) { 61 nsk_jvmti_setFailStatus(); 62 } 63 64 NSK_DISPLAY0("FollowReferences: Invalid initial object:"); 65 // When FollowReferences() is called with an invalid initial object 66 // the behaviour according to the jvmti spec is optional. 67 // It may return JVMTI_ERROR_INVALID_OBJECT and not follow any references. 68 // Or it may treat the object as NULL, and follow all references. 69 // 70 // We will accept both behaviours. We use empty callbacks since the existing 71 // callback marks the test as failed. 72 73 emptyHeapCallbacks.heap_iteration_callback = NULL; 74 emptyHeapCallbacks.heap_reference_callback = NULL; 75 emptyHeapCallbacks.primitive_field_callback = NULL; 76 emptyHeapCallbacks.array_primitive_value_callback = NULL; 77 emptyHeapCallbacks.string_primitive_value_callback = NULL; 78 retCode = NSK_CPP_STUB6(FollowReferences, 79 jvmti, 80 (jint) 0, // heap filter 81 NULL, // class 82 (jobject) &g_wrongHeapCallbacks, // invalid inital object 83 &emptyHeapCallbacks, // No callbacks 84 (const void *) &g_fakeUserData); 85 86 // Accept both JVMTI_ERROR_INVALID_OBJECT and JVMTI_ERROR_NONE 87 if ( ! NSK_VERIFY(retCode == JVMTI_ERROR_INVALID_OBJECT || retCode == JVMTI_ERROR_NONE ) ) { 88 nsk_jvmti_setFailStatus(); 89 } 90 91 NSK_DISPLAY0("FollowReferences: Invalid callbacks:"); 92 93 retCode = NSK_CPP_STUB6(FollowReferences, 94 jvmti, 95 (jint) 0, /* heap filter */ 96 NULL, /* class */ 97 NULL, /* inital object */ 98 NULL, 99 (const void *) &g_fakeUserData); 100 101 if ( ! NSK_VERIFY(retCode == JVMTI_ERROR_NULL_POINTER ) ) { 102 nsk_jvmti_setFailStatus(); 103 } 104 105 NSK_DISPLAY0("GetTag: Invalid object:"); 106 107 retCode = NSK_CPP_STUB3(GetTag, 108 jvmti, 109 (jobject) &g_wrongHeapCallbacks, /* invalid inital object */ 110 &tag); 111 112 if ( ! NSK_VERIFY(retCode == JVMTI_ERROR_INVALID_OBJECT ) ) { 113 nsk_jvmti_setFailStatus(); 114 } 115 116 NSK_DISPLAY0("GetTag: NULL object pointer:"); 117 118 retCode = NSK_CPP_STUB3(GetTag, 119 jvmti, 120 NULL, 121 &tag); 122 123 if ( ! NSK_VERIFY(retCode == JVMTI_ERROR_INVALID_OBJECT ) ) { 124 nsk_jvmti_setFailStatus(); 125 } 126 127 NSK_DISPLAY0("GetTag: NULL tag pointer:"); 128 129 retCode = NSK_CPP_STUB3(GetTag, 130 jvmti, 131 (jobject) &g_wrongHeapCallbacks, 132 NULL); 133 134 if ( ! NSK_VERIFY(retCode == JVMTI_ERROR_NULL_POINTER ) ) { 135 nsk_jvmti_setFailStatus(); 136 } 137 138 NSK_DISPLAY0("SetTag: Invalid object:"); 139 140 tag = 1; 141 retCode = NSK_CPP_STUB3(SetTag, 142 jvmti, 143 (jobject) &g_wrongHeapCallbacks, /* invalid inital object */ 144 tag); 145 146 if ( ! NSK_VERIFY(retCode == JVMTI_ERROR_INVALID_OBJECT ) ) { 147 nsk_jvmti_setFailStatus(); 148 } 149 150 NSK_DISPLAY0("SetTag: NULL object pointer:"); 151 152 retCode = NSK_CPP_STUB3(GetTag, 153 jvmti, 154 NULL, 155 &tag); 156 157 if ( ! NSK_VERIFY(retCode == JVMTI_ERROR_INVALID_OBJECT ) ) { 158 nsk_jvmti_setFailStatus(); 159 } 160 161 NSK_DISPLAY0("GetTag: NULL tag pointer:"); 162 163 } /* verifyReturnCodes */ 164 165 /* ============================================================================= */ 166 167 static void checkNoObjIterated(JNIEnv* jni, jvmtiEnv* jvmti, const char * szClassName) 168 { 169 jvmtiError retCode; 170 jclass klass; 171 172 NSK_DISPLAY1("Verify, that no objects are returned if initial object is %s", szClassName); 173 if (!NSK_JNI_VERIFY(jni, (klass = 174 NSK_CPP_STUB2(FindClass, jni, szClassName)) != NULL)) { 175 nsk_jvmti_setFailStatus(); 176 return; 177 } 178 179 retCode = NSK_CPP_STUB6(FollowReferences, 180 jvmti, 181 (jint) 0, /* heap filter */ 182 klass, /* class */ 183 NULL, /* inital object */ 184 &g_wrongHeapCallbacks, 185 (const void *) &g_fakeUserData); 186 187 if ( ! NSK_VERIFY(retCode == JVMTI_ERROR_NONE ) ) { 188 nsk_jvmti_setFailStatus(); 189 } 190 191 } /* checkNoObjIterated */ 192 193 /* ============================================================================= */ 194 195 /** Agent algorithm. */ 196 197 static void JNICALL agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) 198 { 199 NSK_DISPLAY0("Call FollowReferences() with invalid arguments and check return codes"); 200 201 verifyReturnCodes(jni, jvmti); 202 checkNoObjIterated(jni, jvmti, JAVA_IO_SERIALIZABLE_CLASS_NAME); 203 checkNoObjIterated(jni, jvmti, JAVA_UTIL_CALENDAR_CLASS_NAME); 204 205 NSK_DISPLAY0("Let debugee to finish"); 206 fflush(0); 207 208 if (!NSK_VERIFY(nsk_jvmti_waitForSync(g_timeout))) { 209 return; 210 } 211 212 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) { 213 return; 214 } 215 216 } /* agentProc */ 217 218 219 /* ============================================================================= */ 220 221 /** Agent library initialization. */ 222 223 #ifdef STATIC_BUILD 224 JNIEXPORT jint JNICALL Agent_OnLoad_followref006(JavaVM *jvm, char *options, void *reserved) { 225 return Agent_Initialize(jvm, options, reserved); 226 } 227 JNIEXPORT jint JNICALL Agent_OnAttach_followref006(JavaVM *jvm, char *options, void *reserved) { 228 return Agent_Initialize(jvm, options, reserved); 229 } 230 JNIEXPORT jint JNI_OnLoad_followref006(JavaVM *jvm, char *options, void *reserved) { 231 return JNI_VERSION_1_8; 232 } 233 #endif 234 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) 235 { 236 jvmtiEnv* jvmti = NULL; 237 238 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) { 239 return JNI_ERR; 240 } 241 242 g_timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 243 244 if (!NSK_VERIFY((jvmti = nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) { 245 return JNI_ERR; 246 } 247 248 jvmti_FollowRefObject_init(); 249 250 { 251 jvmtiCapabilities caps; 252 253 memset(&caps, 0, sizeof(caps)); 254 caps.can_tag_objects = 1; 255 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(AddCapabilities, jvmti, &caps))) { 256 return JNI_ERR; 257 } 258 } 259 260 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) { 261 return JNI_ERR; 262 } 263 264 return JNI_OK; 265 266 } /* Agent_OnLoad */ 267 268 269 /* ============================================================================= */ 270 271 }