void JNICALL RequestManager::HandleException()

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


void JNICALL RequestManager::HandleException(jvmtiEnv* jvmti, JNIEnv* jni,
        jthread thread, jmethodID method, jlocation location,
        jobject exception, jmethodID catch_method, jlocation catch_location)
{
    JDWP_TRACE_ENTRY("HandleException(" << jvmti << ',' << jni << ',' << thread
        << ',' << method << ',' << location
        << ',' << exception << ',' << catch_method << ',' << catch_location << ')');

    try {
        jvmtiError err;
        jclass exceptionClass = 0;
        AgentEventRequest* exceptionRequest = 0;

        // if agent was not initialized and this exception is expected, initialize agent
        if (!GetAgentManager().IsStarted()) {
            JDWP_TRACE_PROG("HandleException: initial exception cought");

            // if invocation option onuncaught=y is set, check that exception is uncaught, otherwise return
            if (GetOptionParser().GetOnuncaught() != 0) {
                if (catch_location != 0) {
                    JDWP_TRACE_PROG("HandleException: ignore cougth exception");
                    return;
                }
            }

            // if invocation option onthrow=y is set, check that exception class is expected, otherwise return
            if (GetOptionParser().GetOnthrow() != 0) {

                char* expectedExceptionName = const_cast<char*>(GetOptionParser().GetOnthrow());
                if (expectedExceptionName != 0) {

                    char* exceptionSignature = 0;
                    exceptionClass = jni->GetObjectClass(exception);

                    JVMTI_TRACE(err, jvmti->GetClassSignature(exceptionClass, &exceptionSignature, 0)); 
                    if (err != JVMTI_ERROR_NONE) {
                        throw AgentException(err);
                    }
                    JvmtiAutoFree jafSignature(exceptionSignature);

                    char* exceptionName = GetClassManager().GetClassName(exceptionSignature);
                    JvmtiAutoFree jafName(exceptionName);

                    JDWP_TRACE_PROG("HandleException: exception: class=" << exceptionName 
                         << ", signature=" << exceptionSignature);

                    // compare exception class taking into account similar '/' and '.' delimiters
                    int i;
                    for (i = 0; ; i++) {
                        if (expectedExceptionName[i] != exceptionName[i]) {
                            if ((expectedExceptionName[i] == '.' && exceptionName[i] == '/')
                                    || (expectedExceptionName[i] == '/' && exceptionName[i] == '.')) {
                                 continue;
                            }
                            // ignore not matched exception
                            return;
                        }
                        if (expectedExceptionName[i] == '\0') {
                            // matched exception found
                            break;
                        }
                    }
                }
            }

            // disable catching initial exception and start agent
            JDWP_TRACE_PROG("HandleException: start agent");
            GetAgentManager().DisableInitialExceptionCatch(jvmti, jni);
            GetAgentManager().Start(jvmti, jni);

            // check if VM should be suspended on initial EXCEPTION event
            bool needSuspend = GetOptionParser().GetSuspend();
            if (needSuspend) {
                // add internal EXCEPTION request
                exceptionRequest = new AgentEventRequest(JDWP_EVENT_EXCEPTION, JDWP_SUSPEND_ALL);
                GetRequestManager().AddInternalRequest(jni, exceptionRequest);
            } else {
                return;
            }
        }

        // must be non-agent thread
        if (GetThreadManager().IsAgentThread(jni, thread)) {
            return;
        }

        EventInfo eInfo;
        memset(&eInfo, 0, sizeof(eInfo));
        eInfo.kind = JDWP_EVENT_EXCEPTION;
        eInfo.thread = thread;
        eInfo.method = method;
        eInfo.location = location;

        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);
        }

        if (exceptionClass != 0) {
            eInfo.auxClass = exceptionClass;
        } else {
            eInfo.auxClass = jni->GetObjectClass(exception);
        }
        JDWP_ASSERT(eInfo.auxClass != 0);

        if (catch_method != 0) {
            eInfo.caught = true;
        }

#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("EXCEPTION event:"
                << " class=" << JDWP_CHECK_NULL(eInfo.signature) 
                << " method=" << JDWP_CHECK_NULL(name) 
                << " location=" << eInfo.location
                << " caught=" << (int)eInfo.caught
                << " thread=" << JDWP_CHECK_NULL(info.name));
        }
#endif // NDEBUG

        jint eventCount = 0;
        RequestID *eventList = 0;
        jdwpSuspendPolicy sp = JDWP_SUSPEND_NONE;
        GetRequestManager().GenerateEvents(jni, eInfo, eventCount, eventList, sp);
        AgentAutoFree aafEL(eventList JDWP_FILE_LINE);

        // post generated events
        if (eventCount > 0) {
            jdwpTypeTag typeTag = GetClassManager().GetJdwpTypeTag(eInfo.cls);
            jclass catchCls = 0;
            jdwpTypeTag catchTypeTag = JDWP_TYPE_TAG_CLASS;
            if (catch_method != 0) {
                JVMTI_TRACE(err, GetJvmtiEnv()->GetMethodDeclaringClass(catch_method,
                    &catchCls));
                if (err != JVMTI_ERROR_NONE) {
                    throw AgentException(err);
                }
                catchTypeTag = GetClassManager().GetJdwpTypeTag(catchCls);
            }
            EventComposer *ec = new EventComposer(GetEventDispatcher().NewId(),
                JDWP_COMMAND_SET_EVENT, JDWP_COMMAND_E_COMPOSITE, sp);
            ec->event.WriteInt(eventCount);
            for (jint i = 0; i < eventCount; i++) {
                ec->event.WriteByte(JDWP_EVENT_EXCEPTION);
                ec->event.WriteInt(eventList[i]);
                ec->WriteThread(jni, thread);
                ec->event.WriteLocation(jni,
                    typeTag, eInfo.cls, method, location);
                ec->event.WriteTaggedObjectID(jni, exception);
                ec->event.WriteLocation(jni,
                    catchTypeTag, catchCls, catch_method, catch_location);
            }
            JDWP_TRACE_EVENT("Exception: post set of " << eventCount << " events");
            GetEventDispatcher().PostEventSet(jni, ec, JDWP_EVENT_EXCEPTION);
        }
        // delete internal EXCEPTION request
        if (exceptionRequest != 0) {
            GetRequestManager().DeleteRequest(jni, exceptionRequest);
        }
      /*  JVMTI_TRACE(err, jvmti->SetEventNotificationMode(
             JVMTI_ENABLE , JVMTI_EVENT_BREAKPOINT, thread));*/
    } catch (AgentException& e) {
        JDWP_INFO("JDWP error in EXCEPTION: " << e.what() << " [" << e.ErrCode() << "]");
    }
}