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