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