classmethod.c
来自「基于LWVCL开发的库」· C语言 代码 · 共 2,711 行 · 第 1/5 页
C
2,711 行
readu2(&nr, fp); if (nr == 0) { return true; } if (! checkBufSize(fp, (u2)(nr*(2*4)), CLASS_CNAME(c), einfo)) return false; ic = gc_malloc(sizeof(innerClass) * nr, KGC_ALLOC_CLASSMISC); if (!ic) { postOutOfMemory(einfo); return false; } c->nr_inner_classes = nr; c->inner_classes = ic; for (i = 0; i < nr; i++, ic++) { u2 inner_name_index; readu2(&ic->inner_class, fp); readu2(&ic->outer_class, fp); readu2(&inner_name_index, fp); readu2(&ic->inner_class_accflags, fp); if (inner_name_index != 0) c->kFlags |= KFLAG_ANONYMOUS; if (c->this_index && ic->inner_class == c->this_index) { c->this_inner_index = i; } } return true;}intstartMethods(Hjava_lang_Class* this, u2 methct, errorInfo *einfo){ if (methct == 0) { Kaffe_set_class_methods(this, NULL); } else { Kaffe_set_class_methods(this, gc_malloc(sizeof(Method)*(methct), KGC_ALLOC_METHOD)); if (Kaffe_get_class_methods(this) == NULL) { postOutOfMemory(einfo); return false; } } KGC_WRITE(this, Kaffe_get_class_methods(this)); CLASS_NMETHODS(this) = 0; /* updated in addMethod */ return true;}Method*addMethod(Hjava_lang_Class* c, u2 access_flags, u2 name_index, u2 signature_index, errorInfo *einfo){ constIndex nc; constIndex sc; Method* mt; constants* pool; Utf8Const* name; Utf8Const* signature;#ifdef KAFFE_VMDEBUG int ni;#endif pool = CLASS_CONSTANTS (c); nc = name_index; if (nc >= CLASS_CONST_SIZE (c) || pool->tags[nc] != CONSTANT_Utf8) { /* XXX fill in einfo! */DBG(RESERROR, dprintf("addMethod: no method name.\n"); ); postExceptionMessage(einfo, JAVA_LANG(ClassFormatError), "No method name"); return (NULL); } sc = signature_index; if (sc >= CLASS_CONST_SIZE (c) || pool->tags[sc] != CONSTANT_Utf8) { /* XXX fill in einfo! */DBG(RESERROR, dprintf("addMethod: no signature name.\n"); ); postExceptionMessage(einfo, JAVA_LANG(ClassFormatError), "No signature for method: %s", WORD2UTF (pool->data[nc])->data); return (NULL); } name = WORD2UTF (pool->data[nc]); signature = WORD2UTF (pool->data[sc]);#ifdef KAFFE_VMDEBUG /* Search down class for method name - don't allow duplicates */ for (ni = CLASS_NMETHODS(c), mt = Kaffe_get_class_methods(c); --ni >= 0; ) { assert(! utf8ConstEqual (name, mt->name) || ! utf8ConstEqual (signature, METHOD_SIG(mt))); }#endifDBG(CLASSFILE, dprintf("Adding method %s:%s%s (%x)\n", c->name->data, name->data, signature->data, access_flags); ); mt = &(Kaffe_get_class_methods(c)[CLASS_NMETHODS(c)]); utf8ConstAssign(mt->name, name); METHOD_PSIG(mt) = parseSignature(signature, einfo); if (METHOD_PSIG(mt) == NULL) { return NULL; } mt->class = c; mt->accflags = access_flags; mt->c.bcode.code = NULL; mt->stacksz = 0; mt->localsz = 0; mt->exception_table = NULL; mt->idx = -1; /* Mark constructors as such */ if (utf8ConstEqual (name, constructor_name)) { mt->kFlags |= KFLAG_CONSTRUCTOR; } CLASS_NMETHODS(c)++; return (mt);}Field*addField(Hjava_lang_Class* c, u2 access_flags, u2 name_index, u2 signature_index, errorInfo* einfo){ constIndex nc; constIndex sc; Field* ft; constants* pool; int i; const char* sig; pool = CLASS_CONSTANTS (c); nc = name_index; if (nc >= CLASS_CONST_SIZE (c) || pool->tags[nc] != CONSTANT_Utf8) {DBG(RESERROR, dprintf("addField: no field name.\n"); ); postExceptionMessage(einfo, JAVA_LANG(ClassFormatError), "No field name"); return (NULL); } --CLASS_FSIZE(c); /* holds field count initially */ if (access_flags & ACC_STATIC) { i = CLASS_NSFIELDS(c); } else { i = CLASS_FSIZE(c) + CLASS_NSFIELDS(c); } ft = &CLASS_FIELDS(c)[i]; ft->clazz = c; DBG(CLASSFILE, dprintf("Adding field %s:%s\n", CLASS_CNAME(c), CLASS_CONST_UTF8(c, nc)->data); ); sc = signature_index; if (pool->tags[sc] != CONSTANT_Utf8 || sc >=CLASS_CONST_SIZE(c)) {DBG(RESERROR, dprintf("addField: no signature name.\n"); ); postExceptionMessage(einfo, JAVA_LANG(ClassFormatError), "No signature name for field: %s", CLASS_CONST_UTF8(c, nc)->data); CLASS_NFIELDS(c)++; return (NULL); } utf8ConstAssign(ft->name, WORD2UTF(pool->data[nc])); utf8ConstAssign(ft->signature, CLASS_CONST_UTF8(c, sc)); ft->accflags = access_flags; sig = ft->signature->data; if (sig[0] == 'L' || sig[0] == '[') { /* This `type' field is used to hold a utf8Const describing * the type of the field. This utf8Const will be replaced * with a pointer to an actual class type in resolveFieldType * Between now and then, we add a reference to it. */ ft->accflags |= FIELD_UNRESOLVED_FLAG; FIELD_SIZE(ft) = PTR_TYPE_SIZE; } else { /* NB: since this class is primitive, getClassFromSignature * will not fail. Hence it's okay to pass errorInfo as NULL */ FIELD_TYPE(ft) = getClassFromSignature(sig, NULL, NULL); FIELD_SIZE(ft) = TYPE_PRIM_SIZE(FIELD_TYPE(ft)); } CLASS_NFIELDS(c)++; if (access_flags & ACC_STATIC) { CLASS_NSFIELDS(c)++; } return (ft);}voidsetFieldValue(Hjava_lang_Class* this UNUSED, Field* ft, u2 idx){ /* Set value index */ FIELD_CONSTIDX(ft) = idx; ft->accflags |= FIELD_CONSTANT_VALUE;}intstartFields(Hjava_lang_Class* this, u2 fieldct, errorInfo *einfo){ CLASS_NFIELDS(this) = 0; /* updated in addField() */ CLASS_FSIZE(this) = fieldct; if (fieldct == 0) { CLASS_FIELDS(this) = (Field*)0; } else { CLASS_FIELDS(this) = (Field*) gc_malloc(sizeof(Field) * fieldct, KGC_ALLOC_FIELD); if (!CLASS_FIELDS(this)) { postOutOfMemory(einfo); return false; } } KGC_WRITE(this, CLASS_FIELDS(this)); /* XXX */ return true;}voidfinishFields(Hjava_lang_Class *cl){ Field tmp; Field* fld; int n; /* Reverse the instance fields, so they are in "proper" order. */ fld = CLASS_IFIELDS(cl); n = CLASS_NIFIELDS(cl); while (n > 1) { tmp = fld[0]; fld[0] = fld[n-1]; fld[n-1] = tmp; fld++; n -= 2; }}voidaddMethodCode(Method* m, Code* c){ assert(m != 0); assert(c != 0); assert(c->code != 0); assert(c->code_length != 0); m->c.bcode.code = c->code; m->c.bcode.codelen = c->code_length; m->stacksz = c->max_stack; m->localsz = c->max_locals; m->exception_table = c->exception_table;}voidaddInterfaces(Hjava_lang_Class* c, u2 inr, Hjava_lang_Class** inf){ assert(c); assert(inr > 0); c->interfaces = inf; c->interface_len = inr; KGC_WRITE(c, c->interfaces); /* XXX */}staticHjava_lang_Class *userLoadClass(classEntry *ce, Hjava_lang_ClassLoader *loader, errorInfo *einfo){ Hjava_lang_Class *retval = NULL; Hjava_lang_String *jname; jthrowable excpending; Method *meth; Hjava_lang_Class *class_of_loader; /* * If an exception is already pending, for instance because we're * resolving one that has occurred, save it and clear it for the * upcall. */ excpending = THREAD_DATA()->exceptObj; THREAD_DATA()->exceptObj = NULL; class_of_loader = OBJECT_CLASS((Hjava_lang_Object *)loader); if( (jname = utf8Const2JavaReplace(ce->name, '/', '.')) ) { jvalue jretval; jvalue args[1]; jthrowable excobj; /* If we fail to resolve loadClass then we just have to set retval to NULL. * einfo is already set. */ if ((meth = lookupClassMethod(class_of_loader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;", false, einfo)) == NULL) { retval = NULL; goto userload_done; } if (METHOD_IS_STATIC(meth)) { postExceptionMessage(einfo, "java/lang/NoSuchMethodError", "loadClass is wrongly a static method in %s", CLASS_CNAME(class_of_loader)); retval = NULL; goto userload_done; } /* ClassLoader is not an interface so we may use NATIVECODE directly. */ args[0].l = jname; KaffeVM_safeCallMethodA(meth, METHOD_NATIVECODE(meth), loader, args, &jretval, false); retval = jretval.l; /* * Check whether an exception occurred. If one was pending, * the new exception will override this one. */ excobj = THREAD_DATA()->exceptObj; THREAD_DATA()->exceptObj = NULL; if( excobj != 0 ) { /* There was an exception. */ einfo->type = KERR_RETHROW; einfo->throwable = excobj; if( soft_instanceof(javaLangClassNotFoundException, (Hjava_lang_Object *) einfo->throwable) ) { /* Set this for the verifier. */ einfo->type |= KERR_NO_CLASS_FOUND; } /* We must clear the return value as safeCallMethod does not * handle this. */ retval = NULL; } else if( retval == NULL ) { /* No class returned. */ postExceptionMessage(einfo, JAVA_LANG(ClassNotFoundException), "%s", ce->name->data); /* Set this for the verifier. */ einfo->type |= KERR_NO_CLASS_FOUND; } else if( !utf8ConstEqual(retval->name, ce->name) ) { /* * Its a valid class, but the name differs from the one * that was requested. */ postExceptionMessage( einfo, JAVA_LANG(ClassNotFoundException), "Bad class name (expect: %s, get: %s)", ce->name->data, retval->name->data); /* Set this for the verifier. */ einfo->type |= KERR_NO_CLASS_FOUND; retval = NULL; } else { retval = classMappingLoaded(ce, retval); } } else { postOutOfMemory(einfo); } userload_done: /* rethrow pending exception */ if( excpending != NULL ) { THREAD_DATA()->exceptObj = excpending; } return retval;}Hjava_lang_Class *loadClass(Utf8Const *name, Hjava_lang_ClassLoader *loader, errorInfo *einfo){ Hjava_lang_Class *retval = NULL; classEntry *ce; if( (ce = lookupClassEntry(name, loader, einfo)) ) { if( classMappingSearch(ce, &retval, einfo) ) { if( retval == NULL ) { /* Loading is this thread's responsibility. */ if( loader ) {DBG(VMCLASSLOADER, /* Announce when VM calls class loaders.. */ dprintf("Calling user-defined class loader %s - loadClass(%s)\n", CLASS_CNAME(OBJECT_CLASS(&loader->base)), ce->name->data);); /* Use a user defined loader. */ retval = userLoadClass(ce, loader, einfo); } else {DBG(VMCLASSLOADER, /* Announce when VM calls class loaders.. */ dprintf("Calling internal class loader for %s\n", ce->name->data);); /* Use the primordial loader. */ retval = findClass(ce, einfo); } } else { /* Class is already loaded. */ } if( !retval ) { /* No joy, update state. */ setClassMappingState(ce, NMS_EMPTY); } else if( processClass(retval, CSTATE_LINKED, einfo) == false ) { retval = NULL; } } else { /* Class circularity, or some other error. */ } } else { /* No memory? */ } return( retval );}Hjava_lang_Class*loadArray(Utf8Const* name, Hjava_lang_ClassLoader* loader, errorInfo *einfo){ Hjava_lang_Class *clazz; clazz = getClassFromSignature(&name->data[1], loader, einfo); if (clazz != 0) { if( (clazz = lookupArray(clazz, einfo)) ) { return( clazz ); } else { /* XXX Is it always class not found? */ discardErrorInfo(einfo); postExceptionMessage(einfo, JAVA_LANG(ClassNotFoundException), "%s", name->data); } } else { discardErrorInfo(einfo); postExceptionMessage(einfo, JAVA_LANG(ClassNotFoundException), "%s", name->data); } return (NULL);}/* * Load a class to whose Class object we refer globally. * This is used only for essential classes, so let's bail if this fails. */voidloadStaticClass(Hjava_lang_Class** class, const char* name){ Hjava_lang_Class *clazz; errorInfo info; Utf8Const *utf8; classEntry* centry; bool refAdded; utf8 = utf8ConstFromString(name); if (!utf8) goto bad; centry = lookupClassEntry(utf8, NULL, &info); if (!centry) goto bad; utf8ConstRelease(utf8); lockStaticMutex(¢ry->slock); if (centry->data.cl == 0) { centry->state = NMS_LOADING;DBG(VMCLASSLOADER, /* Announce when VM calls class loaders.. */ dprintf("Calling internal class loader for startup class %s\n", name););
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?