void JNICALL RequestManager::HandleBreakpoint()

in modules/jpda/src/main/native/jdwp/common/agent/core/RequestManager.cpp [1262:1383]


void JNICALL RequestManager::HandleBreakpoint(jvmtiEnv* jvmti, JNIEnv* jni,
        jthread thread, jmethodID method, jlocation location)
{
    JDWP_TRACE_ENTRY("HandleBreakpoint(" << jvmti << ',' << jni << ',' << thread
        << ',' << method << ',' << location << ')');
    
    // if is popFrames process, ignore event
    if (GetThreadManager().IsPopFramesProcess(jni, thread)) {
        return;
    }

    // if occured in agent thread, ignore event
    if (GetThreadManager().IsAgentThread(jni, thread)) {
        return;
    }

    try {
        jvmtiError err;
        EventInfo eInfo;
        memset(&eInfo, 0, sizeof(eInfo));
        eInfo.kind = JDWP_EVENT_BREAKPOINT;
        eInfo.thread = thread;
        eInfo.method = method;
        eInfo.location = location;
        CombinedEventsInfo::CombinedEventsKind combinedKind = CombinedEventsInfo::COMBINED_EVENT_BREAKPOINT;

        // if this combined event was already prediced, ignore event
        if (GetRequestManager().IsPredictedCombinedEvent(jni, eInfo, combinedKind)) {
            return;
        }

        JVMTI_TRACE(err, GetJvmtiEnv()->GetMethodDeclaringClass(method, &eInfo.cls));
        if (err != JVMTI_ERROR_NONE) {
            throw AgentException(err);
        }

        JVMTI_TRACE(err, GetJvmtiEnv()->GetClassSignature(eInfo.cls, &eInfo.signature, 0));
        JvmtiAutoFree jafSignature(eInfo.signature);
        if (err != JVMTI_ERROR_NONE) {
            throw AgentException(err);
        }

#ifndef NDEBUG
        if (JDWP_TRACE_ENABLED(LOG_KIND_EVENT)) {
            char* name = 0;
            JVMTI_TRACE(err, GetJvmtiEnv()->GetMethodName(eInfo.method, &name, 0, 0));

            jvmtiThreadInfo info;
            JVMTI_TRACE(err, GetJvmtiEnv()->GetThreadInfo(thread, &info));

            JDWP_TRACE_EVENT("BREAKPOINT event:"
                << " class=" << JDWP_CHECK_NULL(eInfo.signature) 
                << " method=" << JDWP_CHECK_NULL(name) 
                << " location=" << eInfo.location
                << " thread=" << JDWP_CHECK_NULL(info.name));
        }
#endif // NDEBUG

        // create new info about combined events for this location
        CombinedEventsInfo* combinedEvents = new CombinedEventsInfo();
        combinedEvents->Init(jni, eInfo);
        
        // generate BREAKPOINT events according to existing requests
        jdwpSuspendPolicy sp = JDWP_SUSPEND_NONE;
        CombinedEventsInfo::CombinedEventsList* events = 
            &combinedEvents->m_combinedEventsLists[combinedKind];
        GetRequestManager().GenerateEvents(jni, eInfo, events->count, events->list, sp);
        JDWP_TRACE_EVENT("HandleBreakpoint: BREAKPOINT events:"
                << " count=" << events->count
                << ", suspendPolicy=" << sp 
                << ", location=" << combinedEvents->m_eInfo.location);

        // if no BREAKPOINT events then return from callback
        if (events->count <= 0) {
            combinedEvents->Clean(jni);
            delete combinedEvents;
            combinedEvents = 0;
            return;
        }

        // check if extra combined events should be generated later: METHOD_EXIT
        {
            // check for METHOD_EXIT events
            if (ENABLE_COMBINED_METHOD_EXIT_EVENT) {
                if (GetRequestManager().IsMethodExitLocation(jni, eInfo)) {
                    combinedKind = CombinedEventsInfo::COMBINED_EVENT_METHOD_EXIT;
                    events = &combinedEvents->m_combinedEventsLists[combinedKind];
                    eInfo.kind = JDWP_EVENT_METHOD_EXIT;
                    // generate extra events
                    GetRequestManager().GenerateEvents(jni, eInfo, events->count, events->list, sp);
                    JDWP_TRACE_EVENT("HandleBreakpoint: METHOD_EXIT events:" 
                        << " count=" << events->count
                        << ", suspendPolicy=" << sp 
                        << ", location=" << combinedEvents->m_eInfo.location);
                    // check if corresponding callback should be ignored
                    if (events->count > 0) {
                        events->ignored = 1;
                    }
                }
            }
        }

        // post all generated events
        EventComposer *ec = GetRequestManager().CombineEvents(jni, combinedEvents, sp);
        JDWP_TRACE_EVENT("HandleBreakpoint: post set of " << combinedEvents->GetEventsCount() << " events");
        GetEventDispatcher().PostEventSet(jni, ec, JDWP_EVENT_BREAKPOINT);

        // store info about combined events if other callbacks should be ignored
        if (combinedEvents->GetIgnoredCallbacksCount() > 0) {
            JDWP_TRACE_EVENT("HandleBreakpoint: store combined events for new location:"
                        << " method=" << eInfo.method
                        << " loc=" << eInfo.location);
            GetRequestManager().AddCombinedEventsInfo(jni, combinedEvents);
        } else {
            combinedEvents->Clean(jni);
            delete combinedEvents;
            combinedEvents = 0;
        }
    } catch (AgentException& e) {
        JDWP_INFO("JDWP error in BREAKPOINT: " << e.what() << " [" << e.ErrCode() << "]");
    }
}