/*
 * Log an object with some additional info.
 *
 * Pass in the number of elements in the array (or 0 if this is not an
 * array object), and the number of additional objects that are identical
 * or equivalent to the original.
 */
static void logSummaryLine(const Object* obj, size_t elems, int identical, int equiv)
{
    if (obj == NULL) {
        LOGW("    NULL reference (count=%d)", equiv);
        return;
    }
    if (obj == kClearedJniWeakGlobal) {
        LOGW("    cleared jweak (count=%d)", equiv);
        return;
    }

    std::string className(dvmHumanReadableType(obj));
    if (obj->clazz == gDvm.classJavaLangClass) {
        // We're summarizing multiple instances, so using the exemplar
        // Class' type parameter here would be misleading.
        className = "java.lang.Class";
    }
    if (elems != 0) {
        StringAppendF(&className, " (%zd elements)", elems);
    }

    size_t total = identical + equiv + 1;
    std::string msg(StringPrintf("%5d of %s", total, className.c_str()));
    if (identical + equiv != 0) {
        StringAppendF(&msg, " (%d unique instances)", equiv + 1);
    }
    LOGW("    %s", msg.c_str());
}
Esempio n. 2
0
static void printWaitMessage(const DebugOutputTarget* target, const char* detail, Object* obj,
        Thread* thread)
{
    std::string msg(StringPrintf("  - waiting %s <%p> ", detail, obj));

    if (obj->clazz != gDvm.classJavaLangClass) {
        // I(16573)   - waiting on <0xf5feda38> (a java.util.LinkedList)
        // I(16573)   - waiting on <0xf5ed54f8> (a java.lang.Class<java.lang.ref.ReferenceQueue>)
        msg += "(a " + dvmHumanReadableType(obj) + ")";
    }

    if (thread != NULL) {
        std::string threadName(dvmGetThreadName(thread));
        StringAppendF(&msg, " held by tid=%d (%s)", thread->threadId, threadName.c_str());
    }

    dvmPrintDebugMessage(target, "%s\n", msg.c_str());
}
Esempio n. 3
0
/*
 * Verify that "obj" is non-null and is an instance of "clazz".
 * Used to implement reflection on fields and methods.
 *
 * Returns "false" and throws an exception if not.
 */
bool dvmVerifyObjectInClass(Object* obj, ClassObject* clazz) {
    ClassObject* exceptionClass = NULL;
    if (obj == NULL) {
        exceptionClass = gDvm.exNullPointerException;
    } else if (!dvmInstanceof(obj->clazz, clazz)) {
        exceptionClass = gDvm.exIllegalArgumentException;
    }

    if (exceptionClass == NULL) {
        return true;
    }

    std::string expectedClassName(dvmHumanReadableDescriptor(clazz->descriptor));
    std::string actualClassName(dvmHumanReadableType(obj));
    dvmThrowExceptionFmt(exceptionClass, "expected receiver of type %s, but got %s",
            expectedClassName.c_str(), actualClassName.c_str());
    return false;
}
Esempio n. 4
0
static void throwArgumentTypeMismatch(int argIndex, ClassObject* expected, DataObject* arg) {
    std::string expectedClassName(dvmHumanReadableDescriptor(expected->descriptor));
    std::string actualClassName = dvmHumanReadableType(arg);
    dvmThrowExceptionFmt(gDvm.exIllegalArgumentException, "argument %d should have type %s, got %s",
            argIndex + 1, expectedClassName.c_str(), actualClassName.c_str());
}
/*
 * Dump a summary of an array of references to the log file.
 *
 * This is used to dump the contents of ReferenceTable and IndirectRefTable
 * structs.
 */
void dvmDumpReferenceTableContents(Object* const* refs, size_t count,
                                   const char* descr)
{
    LOGW("%s reference table (%p) dump:", descr, refs);

    if (count == 0) {
        LOGW("  (empty)");
        return;
    }

    // Dump the most recent N entries.
    const size_t kLast = 10;
    int first = count - kLast;
    if (first < 0) {
        first = 0;
    }
    LOGW("  Last %d entries (of %d):", (count - first), count);
    for (int idx = count - 1; idx >= first; --idx) {
        const Object* ref = refs[idx];
        if (ref == NULL) {
            continue;
        }
        if (ref == kClearedJniWeakGlobal) {
            LOGW("    %5d: cleared jweak", idx);
            continue;
        }
        if (ref->clazz == NULL) {
            // should only be possible right after a plain dvmMalloc().
            size_t size = dvmObjectSizeInHeap(ref);
            LOGW("    %5d: %p (raw) (%zd bytes)", idx, ref, size);
            continue;
        }

        std::string className(dvmHumanReadableType(ref));

        std::string extras;
        size_t elems = getElementCount(ref);
        if (elems != 0) {
            StringAppendF(&extras, " (%zd elements)", elems);
        } else if (ref->clazz == gDvm.classJavaLangString) {
            const StringObject* str =
                reinterpret_cast<const StringObject*>(ref);
            extras += " \"";
            size_t count = 0;
            char* s = dvmCreateCstrFromString(str);
            char* p = s;
            for (; *p && count < 16; ++p, ++count) {
                extras += *p;
            }
            if (*p == 0) {
                extras += "\"";
            } else {
                StringAppendF(&extras, "... (%d chars)", str->length());
            }
            free(s);
        }
        LOGW("    %5d: %p %s%s", idx, ref, className.c_str(), extras.c_str());
    }

    // Make a copy of the table, and sort it.
    Object** tableCopy = (Object**)malloc(sizeof(Object*) * count);
    if (tableCopy == NULL) {
        LOGE("Unable to copy table with %d elements", count);
        return;
    }
    memcpy(tableCopy, refs, sizeof(Object*) * count);
    qsort(tableCopy, count, sizeof(Object*), compareObject);
    refs = tableCopy;       // use sorted list

    // Remove any uninteresting stuff from the list. The sort moved them all to the end.
    while (count > 0 && refs[count-1] == NULL) {
        --count;
    }
    while (count > 0 && refs[count-1] == kClearedJniWeakGlobal) {
        --count;
    }
    if (count == 0) {
        return;
    }

    // Dump a summary of the whole table.
    LOGW("  Summary:");
    size_t equiv, identical;
    equiv = identical = 0;
    size_t idx;
    size_t elems;
    for (idx = 1; idx < count; idx++) {
        elems = getElementCount(refs[idx-1]);

        if (refs[idx] == refs[idx-1]) {
            // same reference, added more than once.
            identical++;
        } else if (refs[idx]->clazz == refs[idx-1]->clazz &&
                   getElementCount(refs[idx]) == elems)
        {
            // same class / element count, different object.
            equiv++;
        } else {
            // different class.
            logSummaryLine(refs[idx-1], elems, identical, equiv);
            equiv = identical = 0;
        }
    }

    // Handle the last entry (everything above outputs refs[i-1]).
    elems = getElementCount(refs[idx-1]);
    logSummaryLine(refs[count-1], elems, identical, equiv);

    free(tableCopy);
}