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 jlong timeout = 0; 35 static jboolean eventEnabled = JNI_FALSE; 36 static volatile jboolean eventReceived1 = JNI_FALSE, eventReceived2 = JNI_FALSE; 37 static jclass checkedClass; 38 static jrawMonitorID eventMon; 39 40 41 /* ============================================================================= */ 42 43 static void JNICALL 44 ClassUnload(jvmtiEnv jvmti_env, JNIEnv *jni_env, jthread thread, jclass klass, ...) { 45 /* 46 * With the CMS GC the event can be posted on 47 * a ConcurrentGC thread that is not a JavaThread. 48 * In this case the thread argument can be NULL, so that, 49 * we should not expect the thread argument to be non-NULL. 50 */ 51 if (klass == NULL) { 52 nsk_jvmti_setFailStatus(); 53 NSK_COMPLAIN0("ClassUnload: 'klass' input parameter is NULL.\n"); 54 55 } 56 NSK_DISPLAY0("Received ClassUnload event.\n"); 57 if (eventEnabled == JNI_TRUE) { 58 eventReceived1 = JNI_TRUE; 59 } else { 60 eventReceived2 = JNI_TRUE; 61 } 62 63 /* Notify main agent thread */ 64 if (!NSK_JVMTI_VERIFY( 65 NSK_CPP_STUB2(RawMonitorEnter, jvmti, eventMon))) { 66 nsk_jvmti_setFailStatus(); 67 } 68 if (!NSK_JVMTI_VERIFY( 69 NSK_CPP_STUB2(RawMonitorNotify, jvmti, eventMon))) { 70 nsk_jvmti_setFailStatus(); 71 } 72 if (!NSK_JVMTI_VERIFY( 73 NSK_CPP_STUB2(RawMonitorExit, jvmti, eventMon))) { 74 nsk_jvmti_setFailStatus(); 75 } 76 } 77 78 jboolean isClassUnloadingEnabled() { 79 jint extCount, i; 80 jvmtiExtensionFunctionInfo* extList; 81 jboolean found = JNI_FALSE; 82 jboolean enabled = JNI_FALSE; 83 jvmtiError err; 84 85 NSK_DISPLAY0("Get extension functions list\n"); 86 87 if (!NSK_JVMTI_VERIFY( 88 NSK_CPP_STUB3(GetExtensionFunctions, jvmti, &extCount, &extList))) { 89 nsk_jvmti_setFailStatus(); 90 return JNI_FALSE; 91 } 92 93 for (i = 0; i < extCount; i++) { 94 if (strcmp(extList[i].id, (char*)"com.sun.hotspot.functions.IsClassUnloadingEnabled") == 0) { 95 found = JNI_TRUE; 96 97 err = (*extList[i].func)(jvmti, &enabled); 98 if (err != JVMTI_ERROR_NONE) { 99 NSK_COMPLAIN1("Error during invocation of IsClassUnloadingEnabled function: %d\n", err); 100 nsk_jvmti_setFailStatus(); 101 return JNI_FALSE; 102 } 103 } 104 } 105 if (found == JNI_FALSE) { 106 NSK_COMPLAIN0("IsClassUnloadingEnabled was not found among extension functions.\n"); 107 nsk_jvmti_setFailStatus(); 108 return JNI_FALSE; 109 } 110 111 return enabled; 112 } 113 114 jboolean enableClassUnloadEvent (jboolean enable) { 115 jint extCount, i; 116 jvmtiExtensionEventInfo* extList; 117 jboolean found = JNI_FALSE; 118 119 NSK_DISPLAY0("Get extension events list\n"); 120 if (!NSK_JVMTI_VERIFY( 121 NSK_CPP_STUB3(GetExtensionEvents, jvmti, &extCount, &extList))) { 122 nsk_jvmti_setFailStatus(); 123 return JNI_FALSE; 124 } 125 126 for (i = 0; i < extCount; i++) { 127 if (strcmp(extList[i].id, (char*)"com.sun.hotspot.events.ClassUnload") == 0) { 128 found = JNI_TRUE; 129 130 if (!NSK_JVMTI_VERIFY( 131 NSK_CPP_STUB3(SetExtensionEventCallback, jvmti, extList[i].extension_event_index, 132 enable ? (jvmtiExtensionEvent)ClassUnload : NULL ))) { 133 nsk_jvmti_setFailStatus(); 134 return JNI_FALSE; 135 } 136 eventEnabled = enable; 137 if (enable == JNI_TRUE) { 138 NSK_DISPLAY1("%s callback enabled\n", extList[i].id); 139 } else { 140 NSK_DISPLAY1("%s callback disabled\n", extList[i].id); 141 } 142 } 143 } 144 if (found == JNI_FALSE) { 145 NSK_COMPLAIN0("ClassUnload event was not found among extension events.\n"); 146 nsk_jvmti_setFailStatus(); 147 return JNI_FALSE; 148 } 149 return JNI_TRUE; 150 } 151 152 153 /* ============================================================================= */ 154 155 /** Agent algorithm. */ 156 static void JNICALL 157 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { 158 do { 159 if (isClassUnloadingEnabled() == JNI_FALSE) { 160 NSK_COMPLAIN0("ClassUnloadingEnabled returned false.\n"); 161 nsk_jvmti_setFailStatus(); 162 } 163 164 NSK_DISPLAY0("Wait for loading of ex03t001a class.\n"); 165 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) 166 return; 167 168 if (enableClassUnloadEvent(JNI_TRUE) == JNI_FALSE) { 169 NSK_COMPLAIN0("Cannot set up ClassUnload event callback.\n"); 170 break; 171 } 172 173 NSK_DISPLAY0("Let debugee to unload ex03t001a class.\n"); 174 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) 175 break; 176 177 /* Wait for notifying from event's thread */ 178 if (!NSK_JVMTI_VERIFY( 179 NSK_CPP_STUB2(RawMonitorEnter, jvmti, eventMon))) { 180 nsk_jvmti_setFailStatus(); 181 } 182 if (!NSK_JVMTI_VERIFY( 183 NSK_CPP_STUB3(RawMonitorWait, jvmti, eventMon, timeout))) { 184 nsk_jvmti_setFailStatus(); 185 } 186 if (!NSK_JVMTI_VERIFY( 187 NSK_CPP_STUB2(RawMonitorExit, jvmti, eventMon))) { 188 nsk_jvmti_setFailStatus(); 189 } 190 191 NSK_DISPLAY0("Wait for loading of ex03t001b class.\n"); 192 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) 193 return; 194 195 if (enableClassUnloadEvent(JNI_FALSE) == JNI_FALSE) { 196 NSK_COMPLAIN0("Cannot set off ClassUnload event callback.\n"); 197 break; 198 } 199 200 NSK_DISPLAY0("Let debugee to unload ex03t001b class.\n"); 201 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) 202 return; 203 204 /* Wait during 10 secs for notifying from event's thread */ 205 if (!NSK_JVMTI_VERIFY( 206 NSK_CPP_STUB2(RawMonitorEnter, jvmti, eventMon))) { 207 nsk_jvmti_setFailStatus(); 208 } 209 if (!NSK_JVMTI_VERIFY( 210 NSK_CPP_STUB3(RawMonitorWait, jvmti, eventMon, 10000))) { 211 nsk_jvmti_setFailStatus(); 212 } 213 if (!NSK_JVMTI_VERIFY( 214 NSK_CPP_STUB2(RawMonitorExit, jvmti, eventMon))) { 215 nsk_jvmti_setFailStatus(); 216 } 217 218 if (eventReceived1 == JNI_FALSE) { 219 nsk_jvmti_setFailStatus(); 220 NSK_COMPLAIN0("Expected ClassUnload event was not received.\n"); 221 } 222 223 if (eventReceived2 == JNI_TRUE) { 224 nsk_jvmti_setFailStatus(); 225 NSK_COMPLAIN0("Received unexpected ClassUnload event.\n"); 226 } 227 228 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) 229 return; 230 231 } while (0); 232 233 NSK_TRACE(NSK_CPP_STUB2(DestroyRawMonitor, jvmti, eventMon)); 234 235 NSK_DISPLAY0("Let debugee to finish\n"); 236 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) 237 return; 238 } 239 240 /* ============================================================================= */ 241 242 /** Agent library initialization. */ 243 #ifdef STATIC_BUILD 244 JNIEXPORT jint JNICALL Agent_OnLoad_ex03t001(JavaVM *jvm, char *options, void *reserved) { 245 return Agent_Initialize(jvm, options, reserved); 246 } 247 JNIEXPORT jint JNICALL Agent_OnAttach_ex03t001(JavaVM *jvm, char *options, void *reserved) { 248 return Agent_Initialize(jvm, options, reserved); 249 } 250 JNIEXPORT jint JNI_OnLoad_ex03t001(JavaVM *jvm, char *options, void *reserved) { 251 return JNI_VERSION_1_8; 252 } 253 #endif 254 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 255 256 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 257 return JNI_ERR; 258 259 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 260 261 if (!NSK_VERIFY((jvmti = 262 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 263 return JNI_ERR; 264 265 if (!NSK_JVMTI_VERIFY( 266 NSK_CPP_STUB3(CreateRawMonitor, jvmti, "eventMon", &eventMon))) { 267 return JNI_ERR; 268 } 269 270 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 271 return JNI_ERR; 272 273 return JNI_OK; 274 } 275 276 /* ============================================================================= */ 277 278 }