static void genericHandler(JNIEnv *env, EventInfo *evinfo, HandlerNode *node, struct bag *eventBag) { eventHelper_recordEvent(evinfo, node->handlerID, node->suspendPolicy, eventBag); }
static void handleClassPrepare(JNIEnv *env, JVMDI_Event *event, HandlerNode *node, struct bag *eventBag) { jthread thread = event->u.class_event.thread; jclass clazz = event->u.class_event.clazz; /* We try hard to avoid class loads/prepares in debugger * threads, but it is still possible for them to happen (most * likely for exceptions that are thrown within JNI * methods). If such an event occurs, we must report it, but * we cannot suspend the debugger thread. * * 1) We report the thread as NULL because we don't want the * application to get hold of a debugger thread object. * 2) We try to do the right thing wrt to suspending * threads without suspending debugger threads. If the * requested suspend policy is NONE, there's no problem. If * the requested policy is ALL, we can just suspend all * application threads without producing any surprising * results by leaving the debugger thread running. However, * if the requested policy is EVENT_THREAD, we are forced * to do something different than requested. The most * useful behavior is to suspend all application threads * (just as if the policy was ALL). This allows the * application to operate on the class before it gets into * circulation and so it is preferable to the other * alternative of suspending no threads. */ if (threadControl_isDebugThread(thread)) { event->u.class_event.thread = NULL; if (node->suspendPolicy == JDWP_SuspendPolicy_EVENT_THREAD) { node->suspendPolicy = JDWP_SuspendPolicy_ALL; } } eventHelper_recordEvent(event, node->handlerID, node->suspendPolicy, eventBag); }
/* * Initialize debugger back end modules */ static void initialize(JNIEnv *env, jthread thread, EventIndex triggering_ei) { jvmtiError error; EnumerateArg arg; jbyte suspendPolicy; LOG_MISC(("Begin initialize()")); currentSessionID = 0; initComplete = JNI_FALSE; if ( gdata->vmDead ) { EXIT_ERROR(AGENT_ERROR_INTERNAL,"VM dead at initialize() time"); } /* Turn off the initial JVMTI event notifications */ error = set_event_notification(JVMTI_DISABLE, EI_EXCEPTION); if (error != JVMTI_ERROR_NONE) { EXIT_ERROR(error, "unable to disable JVMTI event notification"); } error = set_event_notification(JVMTI_DISABLE, EI_VM_INIT); if (error != JVMTI_ERROR_NONE) { EXIT_ERROR(error, "unable to disable JVMTI event notification"); } error = set_event_notification(JVMTI_DISABLE, EI_VM_DEATH); if (error != JVMTI_ERROR_NONE) { EXIT_ERROR(error, "unable to disable JVMTI event notification"); } /* Remove initial event callbacks */ (void)memset(&(gdata->callbacks),0,sizeof(gdata->callbacks)); error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventCallbacks) (gdata->jvmti, &(gdata->callbacks), sizeof(gdata->callbacks)); if (error != JVMTI_ERROR_NONE) { EXIT_ERROR(error, "unable to clear JVMTI callbacks"); } commonRef_initialize(); util_initialize(env); threadControl_initialize(); stepControl_initialize(); invoker_initialize(); debugDispatch_initialize(); classTrack_initialize(env); debugLoop_initialize(); initMonitor = debugMonitorCreate("JDWP Initialization Monitor"); /* * Initialize transports */ arg.isServer = isServer; arg.error = JDWP_ERROR(NONE); arg.startCount = 0; transport_initialize(); (void)bagEnumerateOver(transports, startTransport, &arg); /* * Exit with an error only if * 1) none of the transports was successfully started, and * 2) the application has not yet started running */ if ((arg.error != JDWP_ERROR(NONE)) && (arg.startCount == 0) && initOnStartup) { EXIT_ERROR(map2jvmtiError(arg.error), "No transports initialized"); } eventHandler_initialize(currentSessionID); signalInitComplete(); transport_waitForConnection(); suspendPolicy = suspendOnInit ? JDWP_SUSPEND_POLICY(ALL) : JDWP_SUSPEND_POLICY(NONE); if (triggering_ei == EI_VM_INIT) { LOG_MISC(("triggering_ei == EI_VM_INIT")); eventHelper_reportVMInit(env, currentSessionID, thread, suspendPolicy); } else { /* * TO DO: Kludgy way of getting the triggering event to the * just-attached debugger. It would be nice to make this a little * cleaner. There is also a race condition where other events * can get in the queue (from other not-yet-suspended threads) * before this one does. (Also need to handle allocation error below?) */ EventInfo info; struct bag *initEventBag; LOG_MISC(("triggering_ei != EI_VM_INIT")); initEventBag = eventHelper_createEventBag(); (void)memset(&info,0,sizeof(info)); info.ei = triggering_ei; eventHelper_recordEvent(&info, 0, suspendPolicy, initEventBag); (void)eventHelper_reportEvents(currentSessionID, initEventBag); bagDestroyBag(initEventBag); } if ( gdata->vmDead ) { EXIT_ERROR(AGENT_ERROR_INTERNAL,"VM dead before initialize() completes"); } LOG_MISC(("End initialize()")); }