/* * Wrap the now-pending exception in a different exception. This is useful * for reflection stuff that wants to hand a checked exception back from a * method that doesn't declare it. * * If something fails, an (unchecked) exception related to that failure * will be pending instead. */ void dvmWrapException(const char* newExcepStr) { Thread* self = dvmThreadSelf(); Object* origExcep; ClassObject* iteClass; origExcep = dvmGetException(self); dvmAddTrackedAlloc(origExcep, self); // don't let the GC free it dvmClearException(self); // clear before class lookup iteClass = dvmFindSystemClass(newExcepStr); if (iteClass != NULL) { Object* iteExcep; Method* initMethod; iteExcep = dvmAllocObject(iteClass, ALLOC_DEFAULT); if (iteExcep != NULL) { initMethod = dvmFindDirectMethodByDescriptor(iteClass, "<init>", "(Ljava/lang/Throwable;)V"); if (initMethod != NULL) { JValue unused; dvmCallMethod(self, initMethod, iteExcep, &unused, origExcep); /* if <init> succeeded, replace the old exception */ if (!dvmCheckException(self)) dvmSetException(self, iteExcep); } dvmReleaseTrackedAlloc(iteExcep, NULL); /* if initMethod doesn't exist, or failed... */ if (!dvmCheckException(self)) dvmSetException(self, origExcep); } else { /* leave OutOfMemoryError pending */ } } else { /* leave ClassNotFoundException pending */ } assert(dvmCheckException(self)); dvmReleaseTrackedAlloc(origExcep, self); }
/* Throw an OutOfMemoryError if there's a thread to attach it to. * Avoid recursing. * * The caller must not be holding the heap lock, or else the allocations * in dvmThrowException() will deadlock. */ static void throwOOME() { Thread *self; if ((self = dvmThreadSelf()) != NULL) { /* If the current (failing) dvmMalloc() happened as part of thread * creation/attachment before the thread became part of the root set, * we can't rely on the thread-local trackedAlloc table, so * we can't keep track of a real allocated OOME object. But, since * the thread is in the process of being created, it won't have * a useful stack anyway, so we may as well make things easier * by throwing the (stackless) pre-built OOME. */ if (dvmIsOnThreadList(self) && !self->throwingOOME) { /* Let ourselves know that we tried to throw an OOM * error in the normal way in case we run out of * memory trying to allocate it inside dvmThrowException(). */ self->throwingOOME = true; /* Don't include a description string; * one fewer allocation. */ dvmThrowOutOfMemoryError(NULL); } else { /* * This thread has already tried to throw an OutOfMemoryError, * which probably means that we're running out of memory * while recursively trying to throw. * * To avoid any more allocation attempts, "throw" a pre-built * OutOfMemoryError object (which won't have a useful stack trace). * * Note that since this call can't possibly allocate anything, * we don't care about the state of self->throwingOOME * (which will usually already be set). */ #ifdef FASTIVA d2f_setPendingException(self, gDvm.outOfMemoryObj, true); #else dvmSetException(self, gDvm.outOfMemoryObj); #endif } /* We're done with the possible recursion. */ self->throwingOOME = false; } }