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() << "]");
}
}