virtualmachineimpl.c

来自「This is a resource based on j2me embedde」· C语言 代码 · 共 910 行 · 第 1/2 页

C
910
字号
/* * @(#)VirtualMachineImpl.c     1.100 05/03/08 * * Copyright  1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER *  * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation.  *  * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt).  *  * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA  *  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions.  */#include "util.h"#include "VirtualMachineImpl.h"#include "commonRef.h"#include "inStream.h"#include "outStream.h"#include "eventHandler.h"#include "eventHelper.h"#include "threadControl.h"#include "SDE.h"#include "FrameID.h"static char *versionName = "Java Debug Wire Protocol";static int majorVersion = 1;  /* JDWP major version */static int minorVersion = 6;  /* JDWP minor version */static jboolean version(PacketInputStream *in, PacketOutputStream *out){    char buf[500];    char *vmName;    char *vmVersion;    char *vmInfo;        if (gdata->vmDead) {        outStream_setError(out, JDWP_ERROR(VM_DEAD));                            return JNI_TRUE;    }    vmVersion = gdata->property_java_version;    if (vmVersion == NULL) {        vmVersion = "<unknown>";    }    vmName = gdata->property_java_vm_name;    if (vmName == NULL) {        vmName = "<unknown>";    }    vmInfo = gdata->property_java_vm_info;    if (vmInfo == NULL) {        vmInfo = "<unknown>";    }    /*     * Write the descriptive version information     */    (void)snprintf(buf, sizeof(buf),                "%s version %d.%d\nJVM Debug Interface version %d.%d\n"                 "JVM version %s (%s, %s)",                  versionName, majorVersion, minorVersion,                   jvmtiMajorVersion(), jvmtiMinorVersion(),                  vmVersion, vmName, vmInfo);    (void)outStream_writeString(out, buf);    /*     * Write the JDWP version numbers     */    (void)outStream_writeInt(out, majorVersion);    (void)outStream_writeInt(out, minorVersion);    /*     * Write the VM version and name     */    (void)outStream_writeString(out, vmVersion);    (void)outStream_writeString(out, vmName);    return JNI_TRUE;}static jboolean classesForSignature(PacketInputStream *in, PacketOutputStream *out) {    JNIEnv *env;    char *signature;    if (gdata->vmDead) {        outStream_setError(out, JDWP_ERROR(VM_DEAD));                            return JNI_TRUE;    }    signature = inStream_readString(in);    if (signature == NULL) {        outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));        return JNI_TRUE;    }    if (inStream_error(in)) {        return JNI_TRUE;    }    env = getEnv();    WITH_LOCAL_REFS(env, 2000) {            jint classCount;        jclass *theClasses;        jvmtiError error;                error = allLoadedClasses(&theClasses, &classCount);        if ( error == JVMTI_ERROR_NONE ) {            /* Count classes in theClasses which match signature */            int matchCount = 0;            /* Count classes written to the JDWP connection */            int writtenCount = 0;            int i;            for (i=0; i<classCount; i++) {                jclass clazz = theClasses[i];                jint status = classStatus(clazz);                char *candidate_signature = NULL;                jint wanted =                     (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY|                     JVMTI_CLASS_STATUS_PRIMITIVE);                /* We want prepared classes, primitives, and arrays only */                if ((status & wanted) == 0) {                    continue;                }                error = classSignature(clazz, &candidate_signature, NULL);                if (error != JVMTI_ERROR_NONE) {                  break;                }                if (strcmp(candidate_signature, signature) == 0) {                    /* Float interesting classes (those that                     * are matching and are prepared) to the                     * beginning of the array.                      */                    theClasses[i] = theClasses[matchCount];                    theClasses[matchCount++] = clazz;                }                jvmtiDeallocate(candidate_signature);            }                        /* At this point matching prepared classes occupy             * indicies 0 thru matchCount-1 of theClasses.             */            if ( error ==  JVMTI_ERROR_NONE ) {                (void)outStream_writeInt(out, matchCount);                for (; writtenCount < matchCount; writtenCount++) {                    jclass clazz = theClasses[writtenCount];                    jint status = classStatus(clazz);                    jbyte tag = referenceTypeTag(clazz);                    (void)outStream_writeByte(out, tag);                    outStream_writeObjectRef(env, out, clazz);                    (void)outStream_writeInt(out, map2jdwpClassStatus(status));                    /* No point in continuing if there's an error */                    if (outStream_error(out)) {                        break;                    }                }            }        }        if ( error != JVMTI_ERROR_NONE ) {            outStream_setError(out, map2jdwpError(error));        }            } END_WITH_LOCAL_REFS(env);            jvmtiDeallocate(signature);        return JNI_TRUE;}static jboolean allClasses1(PacketInputStream *in, PacketOutputStream *out, int outputGenerics){    JNIEnv *env;    if (gdata->vmDead) {        outStream_setError(out, JDWP_ERROR(VM_DEAD));                            return JNI_TRUE;    }    env = getEnv();    WITH_LOCAL_REFS(env, 2000) {                jint classCount;        jclass *theClasses;        jvmtiError error;            error = allLoadedClasses(&theClasses, &classCount);        if ( error != JVMTI_ERROR_NONE ) {            outStream_setError(out, map2jdwpError(error));        } else {            /* Count classes in theClasses which are prepared */            int prepCount = 0;            /* Count classes written to the JDWP connection */            int writtenCount = 0;              int i;            for (i=0; i<classCount; i++) {                jclass clazz = theClasses[i];                jint status = classStatus(clazz);                jint wanted =                     (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY);                /* We want prepared classes and arrays only */                if ((status & wanted) != 0) {                    /* Float interesting classes (those that                     * are prepared) to the beginning of the array.                      */                    theClasses[i] = theClasses[prepCount];                    theClasses[prepCount++] = clazz;                }            }                    /* At this point prepared classes occupy             * indicies 0 thru prepCount-1 of theClasses.             */            (void)outStream_writeInt(out, prepCount);            for (; writtenCount < prepCount; writtenCount++) {                char *signature = NULL;                char *genericSignature = NULL;                jclass clazz = theClasses[writtenCount];                jint status = classStatus(clazz);                jbyte tag = referenceTypeTag(clazz);                jvmtiError error;                error = classSignature(clazz, &signature, &genericSignature);                if (error != JVMTI_ERROR_NONE) {                    outStream_setError(out, map2jdwpError(error));                    break;                }                (void)outStream_writeByte(out, tag);                outStream_writeObjectRef(env, out, clazz);                (void)outStream_writeString(out, signature);                if (outputGenerics == 1) {                    writeGenericSignature(out, genericSignature);                }                (void)outStream_writeInt(out, map2jdwpClassStatus(status));                jvmtiDeallocate(signature);                if (genericSignature != NULL) {                  jvmtiDeallocate(genericSignature);                }                /* No point in continuing if there's an error */                if (outStream_error(out)) {                    break;                }            }        }        } END_WITH_LOCAL_REFS(env);        return JNI_TRUE;}static jboolean allClasses(PacketInputStream *in, PacketOutputStream *out){    return allClasses1(in, out, 0);}static jboolean allClassesWithGeneric(PacketInputStream *in, PacketOutputStream *out){    return allClasses1(in, out, 1);}  /***********************************************************/static jbooleaninstanceCounts(PacketInputStream *in, PacketOutputStream *out){    jint classCount;    jclass *classes;    JNIEnv *env;    int ii;    if (gdata->vmDead) {        outStream_setError(out, JDWP_ERROR(VM_DEAD));                            return JNI_TRUE;    }    classCount = inStream_readInt(in);    if (inStream_error(in)) {        return JNI_TRUE;    }    if (classCount == 0) {        (void)outStream_writeInt(out, 0);        return JNI_TRUE;    }    if (classCount < 0) {        outStream_setError(out, JDWP_ERROR(ILLEGAL_ARGUMENT));        return JNI_TRUE;    }    env = getEnv();    classes = jvmtiAllocate(classCount * (int)sizeof(jclass));    for (ii = 0; ii < classCount; ii++) {        jdwpError errorCode;        classes[ii] = inStream_readClassRef(env, in);        errorCode = inStream_error(in);        if (errorCode != JDWP_ERROR(NONE)) {            /*             * A class could have been unloaded/gc'd so             * if we get an error, just ignore it and keep              * going.  An instanceCount of 0 will be returned.             */            if (errorCode == JDWP_ERROR(INVALID_OBJECT) ||                errorCode == JDWP_ERROR(INVALID_CLASS)) {                inStream_clearError(in);                classes[ii] = NULL;                continue;            }            jvmtiDeallocate(classes);            return JNI_TRUE;        }    }    WITH_LOCAL_REFS(env, 1) {        jlong      *counts;        jvmtiError error;                counts = jvmtiAllocate(classCount * (int)sizeof(jlong));        /* Iterate over heap getting info on these classes */        error = classInstanceCounts(classCount, classes, counts);        if (error != JVMTI_ERROR_NONE) {            outStream_setError(out, map2jdwpError(error));        } else {            (void)outStream_writeInt(out, classCount);            for (ii = 0; ii < classCount; ii++) {                (void)outStream_writeLong(out, counts[ii]);            }        }        jvmtiDeallocate(counts);    } END_WITH_LOCAL_REFS(env);    jvmtiDeallocate(classes);    return JNI_TRUE;}static jboolean redefineClasses(PacketInputStream *in, PacketOutputStream *out) {    jvmtiClassDefinition *classDefs;    jboolean ok = JNI_TRUE;    jint classCount;    jint i;    JNIEnv *env;    if (gdata->vmDead) {        /* quietly ignore */                        return JNI_TRUE;    }    classCount = inStream_readInt(in);    if (inStream_error(in)) {        return JNI_TRUE;    }    if ( classCount == 0 ) {        return JNI_TRUE;    }    /*LINTED*/    classDefs = jvmtiAllocate(classCount*(int)sizeof(jvmtiClassDefinition));    if (classDefs == NULL) {        outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));        return JNI_TRUE;    }    /*LINTED*/    (void)memset(classDefs, 0, classCount*sizeof(jvmtiClassDefinition));      env = getEnv();    for (i = 0; i < classCount; ++i) {        int byteCount;        unsigned char * bytes;        jclass clazz;                clazz = inStream_readClassRef(env, in);        if (inStream_error(in)) {            ok = JNI_FALSE;            break;        }        byteCount = inStream_readInt(in);        if (inStream_error(in)) {            ok = JNI_FALSE;            break;        }        if ( byteCount <= 0 ) {            outStream_setError(out, JDWP_ERROR(INVALID_CLASS_FORMAT));            ok = JNI_FALSE;            break;        }        bytes = (unsigned char *)jvmtiAllocate(byteCount);        if (bytes == NULL) {            outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));            ok = JNI_FALSE;            break;        }                (void)inStream_readBytes(in, byteCount, (jbyte *)bytes);        if (inStream_error(in)) {            ok = JNI_FALSE;            break;        }        classDefs[i].klass = clazz;        classDefs[i].class_byte_count = byteCount;        classDefs[i].class_bytes = bytes;    }        if (ok == JNI_TRUE) {        jvmtiError error;        error = JVMTI_FUNC_PTR(gdata->jvmti,RedefineClasses)                        (gdata->jvmti, classCount, classDefs);        if (error != JVMTI_ERROR_NONE) {            outStream_setError(out, map2jdwpError(error));        } else {            /* zap our BP info */            for ( i = 0 ; i < classCount; i++ ) {                eventHandler_freeClassBreakpoints(classDefs[i].klass);            }        }    }    /* free up allocated memory */    for ( i = 0 ; i < classCount; i++ ) {        if ( classDefs[i].class_bytes != NULL ) {            jvmtiDeallocate((void*)classDefs[i].class_bytes);        }    }    jvmtiDeallocate(classDefs);    return JNI_TRUE;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?