⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 classloader.c

📁 已经移植好的java虚拟机
💻 C
📖 第 1 页 / 共 4 页
字号:
typedef struct CICmallocs CICmallocs;struct CICcontext {    unsigned char *ptr;    unsigned char *end_ptr;    ClassClass *cb;    jmp_buf jump_buffer;    char **detail;    int pass;         /* two passes, 1 or 2 */    int malloc_size;  /* space needed for everything other than <clinit> */    int clinit_size;  /* space needed for the <clinit> method */    int in_clinit;    /* indicates whether we are loading <clinit> method */    struct {        CICmallocs *mallocs; /* list of memory blocks used in the first pass */        void * alignment_padding;                             /* Whatever follows will be 8-byte aligned */    } pass1;    struct {        char *malloc_buffer; /* used to hold everything other than <clinit> */        char *malloc_ptr;    /* current point of allocation */        char *clinit_buffer; /* used to hold the <clinit> method */        char *clinit_ptr;    /* current point of allocation */    } pass2;};typedef struct CICcontext CICcontext;static char *getAsciz(CICcontext *, bool_t);static char *getAscizFromClass(CICcontext *, int i);static unsigned char get1byte(CICcontext *);static unsigned short get2bytes(CICcontext *);static unsigned long get4bytes(CICcontext *);static void getNbytes(CICcontext *, int count, char *buffer);static void *allocNBytes(CICcontext *, int size);static void freeBuffers(CICcontext *);static void LoadConstantPool(CICcontext *);static void ReadInCode(CICcontext *, struct methodblock *);static void ReadLineTable(CICcontext *, struct methodblock *mb);static void ReadExceptions(CICcontext *, struct methodblock *);static void ReadLocalVars(CICcontext *, struct methodblock *mb);static voidcreateInternalClass0(CICcontext *context, ClassClass *cb,             struct Hjava_lang_ClassLoader *loader, char *name);bool_tcreateInternalClass1(unsigned char *ptr, unsigned char *end_ptr,             ClassClass *cb, struct Hjava_lang_ClassLoader *loader,             char *name, char **detail);/*========================================================================= * FUNCTION:      createInternalClass * OVERVIEW:      Invoked by LoadClassFromFile() or LoadClassFromZip() to *                create an internal class. See createInternalClass1() for *                details. * * INTERFACE: *   parameters:  unsigned char *: ptr *                unsigned char *: end_ptr *                ClassClass *: cb *                struct Hjava_lang_ClassLoader *: loader *                char *: name *                char **: detail * *   returns:     bool_t *=======================================================================*/bool_tcreateInternalClass(unsigned char *ptr, unsigned char *end_ptr,            ClassClass *cb, struct Hjava_lang_ClassLoader *loader,            char *name, char **detail){    bool_t res;    res = createInternalClass1(ptr, end_ptr, cb, loader, name, detail);    return res;}/*========================================================================= * FUNCTION:      JAVA_ERROR * OVERVIEW:      Verifier error processing function. * * INTERFACE: *   parameters:  CICcontext *: context *                char *      : name * *   returns:     nothing *=======================================================================*/void JAVA_ERROR(CICcontext *context, char *name) {    printCurrentClassName();    *(context->detail) = name;    EE()->class_loading_msg = name;    fprintf(stderr, "Class loading error: %s\n", name);    exit(1);}/*========================================================================= * FUNCTION:      createInternalClass1 * OVERVIEW:      Auxiliary function for creating an internal class. *                Invoked by createInternalClass(). * *                Creates an internal class file from the indicated data. *                It should be in a buffer for which the first byte is at *                *ptr and the last byte is just before *end_ptr. *                The class's classloader is indicated by the classloader *                argument. * *                We go through the buffer twice. In the first pass, we *                determine the amount of storage needed by the class. *                We then allocate a single chunk of memory, free the *                temporary storage, and load from the buffer for the second *                time. * *                Since all storage needed by the class initialization method *                <clinit> can be freed after the class is loaded, we count *                the <clinit> space needs separately and store the <clinit> *                method in a separate chunk of memory. * * INTERFACE: *   parameters:  unsigned char *: ptr *                unsigned char *: end_ptr *                ClassClass *: cb *                struct Hjava_lang_ClassLoader *: loader *                char *: name *                char **: detail * *   returns:     bool_t *=======================================================================*/bool_tcreateInternalClass1(unsigned char *ptr, unsigned char *end_ptr,             ClassClass *cb, struct Hjava_lang_ClassLoader *loader,             char *name, char **detail){    struct CICcontext context_block;    struct CICcontext *context = &context_block;    /* Set up the context */    context->ptr = ptr;    context->end_ptr = end_ptr;    context->cb = cb;    context->detail = detail;    /* initialize the remaining fields of the context block */    context->pass = 0;    context->malloc_size = 0;    context->clinit_size = 0;    context->in_clinit = 0;    context->pass1.mallocs = 0;    context->pass2.malloc_buffer = NULL;    context->pass2.malloc_ptr = NULL;    context->pass2.clinit_buffer = NULL;    context->pass2.clinit_ptr = NULL;    if (setjmp(context->jump_buffer)) {        /* We've gotten an error of some sort         * See comments below about zeroing these         * two fields before freeing the temporary         * buffer.         */        cbConstantPool(cb) = NULL;        cbFields(cb) = NULL;        /* Zero out the method so that freeClass will         * not try to free the clinit method.         */        cbMethodsCount(cb) = 0;        freeBuffers(context);        return FALSE;    }    /* The first pass allows us to uncover any class format     * errors and find out the size of the buffer needed.     */    context->pass = 1;    createInternalClass0(context, cb, loader, name);    /* We must set the following two fields to zero before we free     * the temporary buffers, because markClassClass may scan a     * partially constructed class block in the second pass.     * If these two fields are set to zero, markClassClass will     * not scan the constant pool and field blocks, which may     * point to freed memory.     */    cbConstantPool(cb) = NULL;    cbFields(cb) = NULL;    /* Zero out the method so that freeClass will not try     * to free the clinit method.     */    cbMethodsCount(cb) = 0;    freeBuffers(context);    context->ptr = ptr;   /* rewind the raw class data */    if (context->malloc_size > 0) {        context->pass2.malloc_buffer =                   (char *)sysCalloc(1, context->malloc_size);        if (context->pass2.malloc_buffer == 0)            JAVA_ERROR(context, "out of memory");    }    if (context->clinit_size > 0) {        context->pass2.clinit_buffer =                   (char *)sysCalloc(1, context->clinit_size * sizeof(char));        if (context->pass2.clinit_buffer == 0) {            sysFree(context->pass2.malloc_buffer);            JAVA_ERROR(context, "out of memory");        }    }    context->pass2.malloc_ptr = context->pass2.malloc_buffer;    context->pass2.clinit_ptr = context->pass2.clinit_buffer;    /* The second pass accomplishes the real task. */    context->pass = 2;    createInternalClass0(context, cb, loader, name);    /* Valid class - let's put it in the class table. */    AddBinClass(cb);    return TRUE;}/*========================================================================= * FUNCTION:      createInternalClass0 * OVERVIEW:      Auxiliary function invoked by createInternalClass1() during *                the second pass to actually load the internal class file *                structures such as the constant pool, method blocks, field *                blocks and so on. * * INTERFACE: *   parameters:  CICcontext *: ptr *                ClassClass *: cb *                struct Hjava_lang_ClassLoader *: loader *                char *: name * *   returns:     nothing *=======================================================================*/static voidcreateInternalClass0(CICcontext *context, ClassClass *cb,             struct Hjava_lang_ClassLoader *loader, char *name){    int i, j, len;    char buff[BUFSIZ];    char *UTFname = &buff[0];    union cp_item_type *constant_pool;    unsigned char *type_table;    int attribute_count;    unsigned fields_count;    struct methodblock *mb;    struct fieldblock *fb;    struct Classjava_lang_Class *ucb = unhand(cb);    if (get4bytes(context) != JAVA_CLASSFILE_MAGIC)        JAVA_ERROR(context, "Bad magic number");    ucb->minor_version = get2bytes(context);    ucb->major_version = get2bytes(context);    ucb->loader = loader;    /* Ignore version # so that the preverifier can work with JDK 1.4 onwards */    /*    if (ucb->major_version != JAVA_VERSION)        JAVA_ERROR(context, "Bad major version number");    */    LoadConstantPool(context);    constant_pool = ucb->constantpool;    type_table = constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type;    ucb->access = get2bytes(context) & ACC_WRITTEN_FLAGS;    /* Get the name of the class */    i = get2bytes(context); /* index in constant pool of class */    ucb->name = getAscizFromClass(context, i);    /* Conversion for Japanese filenames */    len = native2utf8(name, UTFname, BUFSIZ);    if (name != NULL && strcmp(ucb->name, UTFname) != 0)        JAVA_ERROR(context, "Wrong name");    constant_pool[i].clazz = cb;    CONSTANT_POOL_TYPE_TABLE_SET_RESOLVED(type_table, i);    if (loader) {        /* We don't trust a classloader to do the right thing. . . */        ClassClass **pcb, **end_pcb;        char *name = ucb->name;        if (name == NULL || !IsLegalClassname(name, FALSE)) {            JAVA_ERROR(context, "Bad name");        }        BINCLASS_LOCK();        for (pcb = binclasses, end_pcb = pcb + nbinclasses;                               pcb < end_pcb; pcb++) {            ClassClass *cb = *pcb;            if ((cbLoader(cb) == loader) && (strcmp(name, cbName(cb)) == 0))                break;        }        BINCLASS_UNLOCK();        if (pcb < end_pcb)            /* There's already a class with the same name and loader */            JAVA_ERROR(context, "Duplicate name");    }    /* Get the super class name. */    i = get2bytes(context); /* index in constant pool of class */    if (i > 0) {        ucb->super_name = getAscizFromClass(context, i);        if (!IsLegalClassname(ucb->super_name, FALSE)) {            JAVA_ERROR(context, "Bad superclass name");        }    }    i = ucb->implements_count = get2bytes(context);    if (i > 0) {        int j;        ucb->implements = allocNBytes(context, i * sizeof(short));        for (j = 0; j < i; j++) {            ucb->implements[j] = get2bytes(context);        }    }    fields_count = ucb->fields_count = get2bytes(context);    if (fields_count > 0)        ucb->fields = (struct fieldblock *)          allocNBytes(context, ucb->fields_count * sizeof(struct fieldblock));    for (i = fields_count, fb = ucb->fields; --i >= 0; fb++) {        fieldclass(fb) = cb;        fb->access = get2bytes(context) & ACC_WRITTEN_FLAGS;        fb->name = getAsciz(context, FALSE);        fb->signature = getAsciz(context, FALSE);        attribute_count = get2bytes(context);        for (j = 0; j < (int)attribute_count; j++) {            char *attr_name = getAsciz(context, FALSE);            int length = get4bytes(context);            if (strcmp(attr_name, "ConstantValue") == 0) {                if (fb->access & ACC_STATIC) {                    if (length != 2) {                        JAVA_ERROR(context, "Wrong size for VALUE attribute");                    }                    fb->access |= ACC_VALKNOWN;                    /* we'll change this below */                    fb->u.offset = get2bytes(context);                } else {                    getNbytes(context, length, NULL);                }            } else if (strcmp(attr_name, "Deprecated") == 0) {                if (length > 0) {                    JAVA_ERROR(context, "Bad deprecated size");                }                fb->deprecated = TRUE;            } else if (strcmp(attr_name, "Synthetic") == 0) {                if (length > 0) {                    JAVA_ERROR(context, "Bad synthetic attribute size");                }                fb->synthetic = TRUE;            } else {                getNbytes(context, length, NULL);            }        }        /*        if (fb->access & ACC_STATIC) {            InitializeStaticVar(fb, context);        }        */    }    if ((ucb->methods_count = get2bytes(context)) > 0)        ucb->methods = (struct methodblock *)          allocNBytes(context, ucb->methods_count * sizeof(struct methodblock));    for (i = cbMethodsCount(cb), mb = cbMethods(cb); --i >= 0; mb++) {        fieldclass(&mb->fb) = cb;        mb->fb.access = get2bytes(context) & ACC_WRITTEN_FLAGS;        mb->fb.name = getAsciz(context, FALSE);        mb->fb.signature = getAsciz(context, FALSE);        if (strcmp(mb->fb.name, "<clinit>") == 0 &&            strcmp(mb->fb.signature, "()V") == 0)            context->in_clinit = TRUE;        mb->args_size = Signature2ArgsSize(mb->fb.signature)                    + ((mb->fb.access & ACC_STATIC) ? 0 : 1);        if (mb->args_size > 255)            JAVA_ERROR(context, "Too many arguments");        attribute_count = get2bytes(context);        for (j = 0; j < attribute_count; j++) {            char *attr_name = getAsciz(context, FALSE);            if ((strcmp(attr_name, "Code") == 0)               && ((mb->fb.access & (ACC_NATIVE | ACC_ABSTRACT))==0)) {                ReadInCode(context, mb);            } else if (strcmp(attr_name, "Exceptions") == 0) {                ReadExceptions(context, mb);            } else {                int length = get4bytes(context);                if (strcmp(attr_name, "Deprecated") == 0) {                    if (length > 0) {                        JAVA_ERROR(context, "Bad deprecated size");                    }                    mb->fb.deprecated = TRUE;                } else if (strcmp(attr_name, "Synthetic") == 0) {                    if (length > 0) {                        JAVA_ERROR(context, "Bad synthetic attribute size");                    }                    mb->fb.synthetic = TRUE;                } else {                    getNbytes(context, length, NULL);                }            }        }        context->in_clinit = FALSE;    }    /* See if there are class attributes */    attribute_count = get2bytes(context);    for (j = 0; j < attribute_count; j++) {        char *attr_name = getAsciz(context, FALSE);        int length = get4bytes(context);        if (strcmp(attr_name, "SourceFile") == 0) {            if (length != 2) {                JAVA_ERROR(context, "Wrong size for VALUE attribute");            }

⌨️ 快捷键说明

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