Exemple #1
0
/*
 * Open up the reserved area and throw an exception.  The reserved area
 * should only be needed to create and initialize the exception itself.
 *
 * If we already opened it and we're continuing to overflow, abort the VM.
 *
 * We have to leave the "reserved" area open until the "catch" handler has
 * finished doing its processing.  This is because the catch handler may
 * need to resolve classes, which requires calling into the class loader if
 * the classes aren't already in the "initiating loader" list.
 */
void dvmHandleStackOverflow(Thread* self, const Method* method)
{
    /*
     * Can we make the reserved area available?
     */
    if (self->stackOverflowed) {
        /*
         * Already did, nothing to do but bail.
         */
        LOGE("DalvikVM: double-overflow of stack in threadid=%d; aborting\n",
            self->threadId);
        dvmDumpThread(self, false);
        dvmAbort();
    }

    /* open it up to the full range */
    LOGI("threadid=%d: stack overflow on call to %s.%s:%s\n",
        self->threadId,
        method->clazz->descriptor, method->name, method->shorty);
    StackSaveArea* saveArea = SAVEAREA_FROM_FP(self->curFrame);
    LOGI("  method requires %d+%d+%d=%d bytes, fp is %p (%d left)\n",
        method->registersSize * 4, sizeof(StackSaveArea), method->outsSize * 4,
        (method->registersSize + method->outsSize) * 4 + sizeof(StackSaveArea),
        saveArea, (u1*) saveArea - self->interpStackEnd);
    LOGI("  expanding stack end (%p to %p)\n", self->interpStackEnd,
        self->interpStackStart - self->interpStackSize);
    //dvmDumpThread(self, false);
    self->interpStackEnd = self->interpStackStart - self->interpStackSize;
    self->stackOverflowed = true;

    /*
     * If we were trying to throw an exception when the stack overflowed,
     * we will blow up when doing the class lookup on StackOverflowError
     * because of the pending exception.  So, we clear it and make it
     * the cause of the SOE.
     */
    Object* excep = dvmGetException(self);
    if (excep != NULL) {
        LOGW("Stack overflow while throwing exception\n");
        dvmClearException(self);
    }
    dvmThrowChainedExceptionByClass(gDvm.classJavaLangStackOverflowError,
        NULL, excep);
}
/*
 * Create a Throwable and throw an exception in the current thread (where
 * "throwing" just means "set the thread's exception pointer").
 *
 * "msg" and/or "cause" may be NULL.
 *
 * If we have a bad exception hierarchy -- something in Throwable.<init>
 * is missing -- then every attempt to throw an exception will result
 * in another exception.  Exceptions are generally allowed to "chain"
 * to other exceptions, so it's hard to auto-detect this problem.  It can
 * only happen if the system classes are broken, so it's probably not
 * worth spending cycles to detect it.
 *
 * We do have one case to worry about: if the classpath is completely
 * wrong, we'll go into a death spin during startup because we can't find
 * the initial class and then we can't find NoClassDefFoundError.  We have
 * to handle this case.
 *
 * [Do we want to cache pointers to common exception classes?]
 */
void dvmThrowChainedException(const char* exceptionDescriptor, const char* msg,
    Object* cause)
{
    ClassObject* excepClass;

    LOGV("THROW '%s' msg='%s' cause=%s\n",
        exceptionDescriptor, msg,
        (cause != NULL) ? cause->clazz->descriptor : "(none)");

    if (gDvm.initializing) {
        if (++gDvm.initExceptionCount >= 2) {
            LOGE("Too many exceptions during init (failed on '%s' '%s')\n",
                exceptionDescriptor, msg);
            dvmAbort();
        }
    }

    excepClass = dvmFindSystemClass(exceptionDescriptor);
    if (excepClass == NULL) {
        /*
         * We couldn't find the exception class.  The attempt to find a
         * nonexistent class should have raised an exception.  If no
         * exception is currently raised, then we're pretty clearly unable
         * to throw ANY sort of exception, and we need to pack it in.
         *
         * If we were able to throw the "class load failed" exception,
         * stick with that.  Ideally we'd stuff the original exception
         * into the "cause" field, but since we can't find it we can't
         * do that.  The exception class name should be in the "message"
         * field.
         */
        if (!dvmCheckException(dvmThreadSelf())) {
            LOGE("FATAL: unable to throw exception (failed on '%s' '%s')\n",
                exceptionDescriptor, msg);
            dvmAbort();
        }
        return;
    }

    dvmThrowChainedExceptionByClass(excepClass, msg, cause);
}