jvmtiexport.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 2,241 行 · 第 1/5 页
C
2,241 行
/* * These functions maintain the linked list of currently running threads. */CVMJvmtiThreadNode *CVMjvmtiFindThread(CVMExecEnv* ee, CVMObjectICell* thread){ CVMJvmtiThreadNode *node; CVMBool thrEq; JVMTI_LOCK(ee); /* cast away volatility */ node = (CVMJvmtiThreadNode *)CVMglobals.jvmti.statics.threadList; while (node != NULL) { CVMID_icellSameObject(ee, node->thread, thread, thrEq); if (thrEq) { break; } node = node->next; } JVMTI_UNLOCK(ee); return node;}CVMJvmtiThreadNode *CVMjvmtiInsertThread(CVMExecEnv* ee, CVMObjectICell* thread){ CVMJvmtiThreadNode *node; /* NOTE: you could move the locking and unlocking inside the if clause in such a way as to avoid the problem with seizing both the debugger and global root lock at the same time, but it wouldn't solve the problem of removeThread, which is harder, nor the (potential) problem of the several routines which perform indirect memory accesses while holding the debugger lock; if there was ever a lock associated with those accesses there would be a problem. */ JVMTI_LOCK(ee); node = (CVMJvmtiThreadNode *)malloc(sizeof(*node)); if (node != NULL) { memset(node, 0, sizeof(*node)); node->thread = CVMID_getGlobalRoot(ee); if (node->thread == NULL) { goto fail0; } node->lastDetectedException = CVMID_getGlobalRoot(ee); if (node->lastDetectedException == NULL) { goto fail1; } CVMID_icellAssign(ee, node->thread, thread); /* cast away volatility */ node->next = (CVMJvmtiThreadNode *)CVMglobals.jvmti.statics.threadList; CVMglobals.jvmti.statics.threadList = node; } unlock: JVMTI_UNLOCK(ee); return node; fail1: CVMID_freeGlobalRoot(ee, node->thread); fail0: free(node); node = NULL; goto unlock;}jboolean CVMjvmtiRemoveThread(CVMExecEnv* ee, CVMObjectICell* thread){ CVMJvmtiThreadNode *previous = NULL; CVMJvmtiThreadNode *node; CVMBool thrEq; jboolean rc = JNI_FALSE; JVMTI_LOCK(ee); /* cast away volatility */ node = (CVMJvmtiThreadNode *)CVMglobals.jvmti.statics.threadList; while (node != NULL) { CVMID_icellSameObject(ee, node->thread, thread, thrEq); if (thrEq) { if (previous == NULL) { CVMglobals.jvmti.statics.threadList = node->next; } else { previous->next = node->next; } CVMID_freeGlobalRoot(ee, node->thread); CVMID_freeGlobalRoot(ee, node->lastDetectedException); free((void *)node); rc = JNI_TRUE; break; } previous = node; node = node->next; } JVMTI_UNLOCK(ee); return rc;}static voidcheckAndSendStartEvent(CVMExecEnv *ee){ CVMJvmtiThreadNode *node = CVMjvmtiFindThread(ee, CVMcurrentThreadICell(ee)); if (node == NULL || node->startEventSent == CVM_FALSE) { /* Send thread start event */ CVMjvmtiPostThreadStartEvent(ee, CVMcurrentThreadICell(ee)); }}static voidunlock_monitors(CVMExecEnv* threadEE) { CVMOwnedMonitor *mon, *monNext; CVMFrame *currentFrame; CVMJvmtiLockInfo *li; CVMObjectICell objIcell; CVMObjectICell *objp = &objIcell; CVMExecEnv *ee =CVMgetEE(); mon = threadEE->objLocksOwned; currentFrame = CVMeeGetCurrentFrame(threadEE); CVMassert(CVMframeIsJava(currentFrame)); li = CVMgetJavaFrame(currentFrame)->jvmtiLockInfo; while (li != NULL) { mon = li->lock; monNext = mon->next;#ifdef CVM_DEBUG CVMassert(mon->state != CVM_OWNEDMON_FREE);#endif if (mon->object != NULL) { CVMD_gcUnsafeExec(ee, { if(!CVMobjectTryUnlock(threadEE, mon->object)) { CVMID_icellSetDirect(ee, objp, mon->object); CVMobjectUnlock(threadEE, objp); } }); } /* unlocking lock removes lockinfo record */ li = CVMgetJavaFrame(currentFrame)->jvmtiLockInfo; }}voidreportException(CVMExecEnv* ee, CVMUint8 *pc, CVMObjectICell* object, CVMFrame* frame) { JNIEnv *env = CVMexecEnv2JniEnv(ee); CVMMethodBlock* exceptionMb = frame->mb; CVMClassBlock* exceptionCb; CVMJavaLong catchLocation = 0L; CVMMethodBlock *catchMb = NULL; CVMJvmtiContext *context; jvmtiEventException callback; CVMFrameIterator iter; if (exceptionMb == NULL) { return; } /* NOTE: MUST BE A JAVA METHOD */ CVMassert(!CVMmbIs(exceptionMb, NATIVE)); CVMID_objectGetClass(ee, object, exceptionCb); context = GLOBAL_ENV; callback = context->eventCallbacks.Exception; if (callback != NULL) { /* walk up the stack to see if this exception is caught anywhere. */ CVMframeIterateInit(&iter, frame); while (CVMframeIterateNextReflection(&iter, CVM_TRUE)) { /* %comment: k004 */ /* skip transition frames, which can't catch exceptions */ if (CVMframeIterateCanHaveJavaCatchClause(&iter)) { catchMb = CVMframeIterateGetMb(&iter); /* %comment: k005 */ if (catchMb != NULL) { CVMUint8* pc = CVMframeIterateGetJavaPc(&iter); CVMUint8* cpc = CVMgcSafeFindPCForException(ee, &iter, exceptionCb, pc); if (cpc != NULL) { /* NOTE: MUST BE A JAVA METHOD */ CVMassert(!CVMmbIs(catchMb, NATIVE)); catchLocation = CVMint2Long(cpc - CVMmbJavaCode(catchMb)); break; } else { catchMb = NULL; } } } } (*callback)(&context->jvmtiExternal, env, (*env)->NewLocalRef(env, CVMcurrentThreadICell(ee)), exceptionMb, CVMint2Long(pc - CVMmbJavaCode(exceptionMb)), (*env)->NewLocalRef(env, object), catchMb, catchLocation); }}/* FIXME: This function is being called if JVMTI is being enabled globally even if this event is not enabled. This is vey heavy overhead and should be fixed. *//* %comment: k006 */voidCVMjvmtiPostExceptionEvent(CVMExecEnv* ee, CVMUint8 *pc, CVMObjectICell* object){ JNIEnv *env = CVMexecEnv2JniEnv(ee); CVMJvmtiThreadNode *threadNode; CVMBool exceptionsEqual = CVM_FALSE; CVMJVMTI_CHECK_PHASEV(JVMTI_PHASE_LIVE); /* This check is probably unnecessary */ if (CVMcurrentThreadICell(ee) == NULL) { return; } if (!MUST_NOTIFY_THREAD(ee, JVMTI_EVENT_EXCEPTION)) { return; } checkAndSendStartEvent(ee); threadNode = CVMjvmtiFindThread(ee, CVMcurrentThreadICell(ee));#if 0 if (threadNode == NULL) { /* ignore any exceptions before thread start */ return; }#endif CVMID_icellSameObject(ee, threadNode->lastDetectedException, object, exceptionsEqual); if (!exceptionsEqual) { CVMStack *curStack = &ee->interpreterStack; CVMObjectICell *exceptionRef; CVMFrame* frame = CVMeeGetCurrentFrame(ee); CVMBool stackBumped = CVM_FALSE; CVMassert(CVMID_icellIsNull(CVMmiscICell(ee))); if (CVMlocalExceptionOccurred(ee)) { CVMID_icellAssign(ee, CVMmiscICell(ee), CVMlocalExceptionICell(ee)); CVMclearLocalException(ee); } else { CVMID_icellAssign(ee, CVMmiscICell(ee), CVMremoteExceptionICell(ee)); CVMclearRemoteException(ee); } if ((*env)->PushLocalFrame(env, 5+LOCAL_FRAME_SLOP) < 0) { /* stack overflow, enable reserve */ CVMclearLocalException(ee); CVMstackEnableReserved(curStack); if ((*env)->PushLocalFrame(env, 5+LOCAL_FRAME_SLOP) < 0) { /* OK, now we have really failed */ CVMstackDisableReserved(curStack); goto cleanup; } stackBumped = CVM_TRUE; } /* OK, we now have a frame so create a local ref to hold the exception */ exceptionRef = (*env)->NewLocalRef(env, CVMmiscICell(ee)); CVMID_icellSetNull(CVMmiscICell(ee)); /* * Save the pending exception so it does not get * overwritten if CVMgcSafeFindPCForException() throws an * exception. Also, in classloading builds, * CVMgcSafeFindPCForException may cause loading of the * exception class, which code expects no exception to * have occurred upon entry. */ reportException(ee, pc, exceptionRef, frame); /* * This needs to be a global ref; otherwise, the detected * exception could be cleared and collected in a native method * causing later comparisons to be invalid. */ CVMID_icellAssign(ee, threadNode->lastDetectedException, object); CVMID_icellAssign(ee, CVMmiscICell(ee), exceptionRef); (*env)->PopLocalFrame(env, 0); cleanup: if (stackBumped) { CVMstackDisableReserved(curStack); } CVMclearLocalException(ee); CVMgcSafeThrowLocalException(ee, CVMmiscICell(ee)); CVMID_icellSetNull(CVMmiscICell(ee)); }}/* FIXME: This function is being called from the interpreter loop if JVMTI is enabed globally even if this event is not needed. This has to heavy overhead and needs to be fixed. *//* * This function is called by the interpreter whenever: * 1) The interpreter catches an exception, or * 2) The interpreter detects that a native method has returned * without an exception set (i.e. the native method *may* have * cleared an exception; cannot tell for sure) * * This function performs 2 tasks. It removes any exception recorded * as the last detected exception by notify_debugger_of_exception. It * also reports an event to the JVMTI client. (2) above implies that * we need to make sure that an exception was actually cleared before * reporting the event. This * can be done by checking whether there is currently a last detected * detected exception value saved for this thread. */voidCVMjvmtiPostExceptionCatchEvent(CVMExecEnv* ee, CVMUint8 *pc, CVMObjectICell* object){ CVMJvmtiThreadNode *threadNode; CVMJvmtiContext *context; jvmtiEventExceptionCatch callback; JNIEnv* env = CVMexecEnv2JniEnv(ee); CVMFrame* frame; CVMMethodBlock* mb; CVMJVMTI_CHECK_PHASEV(JVMTI_PHASE_LIVE); /* This check is probably unnecessary */ if (CVMcurrentThreadICell(ee) == NULL) { return; } if (!MUST_NOTIFY_THREAD(ee, JVMTI_EVENT_EXCEPTION_CATCH)) { return; } checkAndSendStartEvent(ee); threadNode = CVMjvmtiFindThread(ee, CVMcurrentThreadICell(ee));#if 0 if (threadNode == NULL) { /* ignore any exceptions before thread start */ return; }#endif frame = CVMeeGetCurrentFrame(ee); mb = frame->mb; if (mb == NULL) { return; } /* NOTE: MUST BE A JAVA METHOD */ CVMassert(!CVMmbIs(mb, NATIVE)); /* * Report the caught exception if it is being caught in Java code * or if it was caught in native code after its throw was reported * earlier. */ if ((object != NULL) || !CVMID_icellIsNull(threadNode->lastDetectedException)) { if ((*env)->PushLocalFrame(env, 3+LOCAL_FRAME_SLOP) < 0) { return; } context = GLOBAL_ENV; callback = context->eventCallbacks.ExceptionCatch; if (callback != NULL) { (*callback)(&context->jvmtiExternal, env, (*env)->NewLocalRef(env, CVMcurrentThreadICell(ee)), mb, CVMint2Long(pc - CVMmbJavaCode(mb)), (*env)->NewLocalRef(env, object)); } (*env)->PopLocalFrame(env, 0); } CVMID_icellSetNull(threadNode->lastDetectedException);}voidCVMjvmtiPostSingleStepEvent(CVMExecEnv* ee, CVMUint8 *pc){ /* * The interpreter notifies us only for threads that have stepping enabled, * so we don't do any checks of the global or per-thread event * enable flags here. */ CVMJVMTI_CHECK_PHASEV(JVMTI_PHASE_LIVE); if (CVMjvmtiIsEnabled()) { CVMFrame* frame = CVMeeGetCurrentFrame(ee); CVMMethodBlock* mb = frame->mb; JNIEnv* env = CVMexecEnv2JniEnv(ee); CVMJvmtiContext *context; jvmtiEventSingleStep callback; if (CVMframeIsTransition(frame) || mb == NULL) { return; } /* NOTE: MUST BE A JAVA METHOD */ CVMassert(!CVMmbIs(mb, NATIVE)); CVMtraceJVMTI(("JVMTI: Post Step: ee 0x%x\n", (int)ee)); if ((*env)->PushLocalFrame(env, 2+LOCAL_FRAME_SLOP) < 0) { return; } context = GLOBAL_ENV; callback = context->eventCallbacks.SingleStep; if (callback != NULL) { (*callback)(&context->jvmtiExternal, env, (*env)->NewLocalRef(env, CVMcurrentThreadICell(ee)), mb, CVMint2Long(pc - CVMmbJavaCode(mb))); } (*env)->PopLocalFrame(env, 0); } if (CVMjvmtiNeedFramePop(ee)) { unlock_monitors(ee); }}voidnotify_debugger_of_breakpoint(CVMExecEnv* ee, CVMUint8 *pc){ CVMJVMTI_CHECK_PHASEV(JVMTI_PHASE_LIVE); if (MUST_NOTIFY_THREAD(ee, JVMTI_EVENT_BREAKPOINT)) { CVMFrame* frame = CVMeeGetCurrentFrame(ee); CVMMethodBlock* mb = frame->mb; JNIEnv *env = CVMexecEnv2JniEnv(ee); CVMJvmtiContext *context; jvmtiEventBreakpoint callback; if (mb == NULL) { return; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?