Esempio n. 1
0
/*
 * Generate the contents of a THST chunk.  The data encompasses all known
 * threads.
 *
 * Response has:
 *  (1b) header len
 *  (1b) bytes per entry
 *  (2b) thread count
 * Then, for each thread:
 *  (4b) threadId
 *  (1b) thread status
 *  (4b) tid
 *  (4b) utime 
 *  (4b) stime 
 *  (1b) is daemon?
 *
 * The length fields exist in anticipation of adding additional fields
 * without wanting to break ddms or bump the full protocol version.  I don't
 * think it warrants full versioning.  They might be extraneous and could
 * be removed from a future version.
 *
 * Returns a new byte[] with the data inside, or NULL on failure.  The
 * caller must call dvmReleaseTrackedAlloc() on the array.
 */
ArrayObject* dvmDdmGenerateThreadStats(void)
{
    const int kHeaderLen = 4;
    const int kBytesPerEntry = 18;

    dvmLockThreadList(NULL);

    Thread* thread;
    int threadCount = 0;
    for (thread = gDvm.threadList; thread != NULL; thread = thread->next)
        threadCount++;

    /*
     * Create a temporary buffer.  We can't perform heap allocation with
     * the thread list lock held (could cause a GC).  The output is small
     * enough to sit on the stack.
     */
    int bufLen = kHeaderLen + threadCount * kBytesPerEntry;
    u1 tmpBuf[bufLen];
    u1* buf = tmpBuf;

    set1(buf+0, kHeaderLen);
    set1(buf+1, kBytesPerEntry);
    set2BE(buf+2, (u2) threadCount);
    buf += kHeaderLen;

    pid_t pid = getpid();
    for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
        unsigned long utime, stime;
        bool isDaemon;

        if (!getThreadStats(pid, thread->systemTid, &utime, &stime)) {
            // failed; drop in empty values
            utime = stime = 0;
        }

        isDaemon = dvmGetFieldBoolean(thread->threadObj,
                        gDvm.offJavaLangThread_daemon);

        set4BE(buf+0, thread->threadId);
        set1(buf+4, thread->status);
        set4BE(buf+5, thread->systemTid);
        set4BE(buf+9, utime);
        set4BE(buf+13, stime);
        set1(buf+17, isDaemon);

        buf += kBytesPerEntry;
    }
    dvmUnlockThreadList();


    /*
     * Create a byte array to hold the data.
     */
    ArrayObject* arrayObj = dvmAllocPrimitiveArray('B', bufLen, ALLOC_DEFAULT);
    if (arrayObj != NULL)
        memcpy(arrayObj->contents, tmpBuf, bufLen);
    return arrayObj;
}
Esempio n. 2
0
/*
 * Dump some information about an object.
 */
void dvmDumpObject(const Object* obj)
{
    ClassObject* clazz;
    int i;

    if (obj == NULL || obj->clazz == NULL) {
        LOGW("Null or malformed object not dumped\n");
        return;
    }

    clazz = obj->clazz;
    LOGD("----- Object dump: %p (%s, %d bytes) -----\n",
        obj, clazz->descriptor, (int) clazz->objectSize);
    //printHexDump(obj, clazz->objectSize);
    LOGD("  Fields:\n");
    while (clazz != NULL) {
        LOGD("    -- %s\n", clazz->descriptor);
        for (i = 0; i < clazz->ifieldCount; i++) {
            const InstField* pField = &clazz->ifields[i];
            char type = pField->field.signature[0];

            if (type == 'F' || type == 'D') {
                double dval;

                if (type == 'F')
                    dval = dvmGetFieldFloat(obj, pField->byteOffset);
                else
                    dval = dvmGetFieldDouble(obj, pField->byteOffset);

                LOGD("    %2d: '%s' '%s' af=%04x off=%d %.3f\n", i,
                    pField->field.name, pField->field.signature,
                    pField->field.accessFlags, pField->byteOffset, dval);
            } else {
                u8 lval;

                if (type == 'J')
                    lval = dvmGetFieldLong(obj, pField->byteOffset);
                else if (type == 'Z')
                    lval = dvmGetFieldBoolean(obj, pField->byteOffset);
                else
                    lval = dvmGetFieldInt(obj, pField->byteOffset);

                LOGD("    %2d: '%s' '%s' af=%04x off=%d 0x%08llx\n", i,
                    pField->field.name, pField->field.signature,
                    pField->field.accessFlags, pField->byteOffset, lval);
            }
        }

        clazz = clazz->super;
    }
}
Esempio n. 3
0
/*
 * dump一些关于某个对象的信息
 *
 */
void dvmDumpObject(const Object* obj)
{
    ClassObject* clazz;
    int i;

    if (obj == NULL || obj->clazz == NULL) {
        ALOGW("Null or malformed object not dumped");
        return;
    }

    clazz = obj->clazz;
    ALOGD("----- Object dump: %p (%s, %d bytes) -----",
        obj, clazz->descriptor, (int) clazz->objectSize);
    //printHexDump(obj, clazz->objectSize);
    ALOGD("  Fields:");
    while (clazz != NULL) {
        ALOGD("    -- %s", clazz->descriptor);
        for (i = 0; i < clazz->ifieldCount; i++) {
            const InstField* pField = &clazz->ifields[i];
            char type = pField->signature[0];

            if (type == 'F' || type == 'D') {
                double dval;

                if (type == 'F')
                    dval = dvmGetFieldFloat(obj, pField->byteOffset);
                else
                    dval = dvmGetFieldDouble(obj, pField->byteOffset);

                ALOGD("    %2d: '%s' '%s' af=%04x off=%d %.3f", i,
                    pField->name, pField->signature,
                    pField->accessFlags, pField->byteOffset, dval);
            } else {
                u8 lval;

                if (type == 'J')
                    lval = dvmGetFieldLong(obj, pField->byteOffset);
                else if (type == 'Z')
                    lval = dvmGetFieldBoolean(obj, pField->byteOffset);
                else
                    lval = dvmGetFieldInt(obj, pField->byteOffset);

                ALOGD("    %2d: '%s' '%s' af=%04x off=%d 0x%08llx", i,
                    pField->name, pField->signature,
                    pField->accessFlags, pField->byteOffset, lval);
            }
        }

        clazz = clazz->super;
    }
    if (dvmIsClassObject(obj)) {
        ALOGD("  Static fields:");
        const StaticField* sfields = &((ClassObject *)obj)->sfields[0];
        for (i = 0; i < ((ClassObject *)obj)->sfieldCount; ++i) {
            const StaticField* pField = &sfields[i];
            size_t byteOffset = (size_t)pField - (size_t)sfields;
            char type = pField->signature[0];

            if (type == 'F' || type == 'D') {
                double dval;

                if (type == 'F')
                    dval = pField->value.f;
                else
                    dval = pField->value.d;

                ALOGD("    %2d: '%s' '%s' af=%04x off=%zd %.3f", i,
                     pField->name, pField->signature,
                     pField->accessFlags, byteOffset, dval);
            } else {
                u8 lval;

                if (type == 'J')
                    lval = pField->value.j;
                else if (type == 'Z')
                    lval = pField->value.z;
                else
                    lval = pField->value.i;

                ALOGD("    %2d: '%s' '%s' af=%04x off=%zd 0x%08llx", i,
                     pField->name, pField->signature,
                     pField->accessFlags, byteOffset, lval);
            }
        }
    }
}