classmethod.c
来自「基于LWVCL开发的库」· C语言 代码 · 共 2,711 行 · 第 1/5 页
C
2,711 行
DO_CLASS_STATE(CSTATE_COMPLETE) { jthrowable exc = NULL; jthrowable excpending; /* If we need a successfully initialized class here, but its * initializer failed, return false as well */ if (class->state == CSTATE_FAILED) { postExceptionMessage(einfo, JAVA_LANG(NoClassDefFoundError), "%s", class->name->data); success = false; goto done; }DBG(STATICINIT, dprintf("Initialising %s static %d\n", class->name->data, CLASS_FSIZE(class)); ); meth = findMethodLocal(class, init_name, void_signature); if (meth == NULL) { SET_CLASS_STATE(CSTATE_COMPLETE); goto done; } if (class->state == CSTATE_DOING_INIT) { if (THREAD_NATIVE() == class->processingThread) { goto done; } else { while (class->state == CSTATE_DOING_INIT) { waitOnClass(class); goto retry; } } } SET_CLASS_STATE(CSTATE_DOING_INIT); class->processingThread = THREAD_NATIVE(); /* give classLock up for the duration of this call */ unlockClass(class); /* We use here an exception safe call method to be able * to catch possible exceptions which may occur. */ excpending = THREAD_DATA()->exceptObj; THREAD_DATA()->exceptObj = NULL; KaffeVM_safeCallMethodA(meth, METHOD_NATIVECODE(meth), NULL, NULL, NULL, 0); exc = THREAD_DATA()->exceptObj; THREAD_DATA()->exceptObj = excpending; lockClass(class); class->processingThread = NULL; if (exc != 0) { if( soft_instanceof(javaLangException, exc) ) { /* this is special-cased in throwError */ einfo->type = (KERR_INITIALIZER_ERROR | KERR_NO_CLASS_FOUND); einfo->throwable = exc; } else { /* Should be an error... */ einfo->type = (KERR_RETHROW | KERR_NO_CLASS_FOUND); einfo->throwable = exc; } /* * we return false here because COMPLETE fails */ success = false; SET_CLASS_STATE(CSTATE_FAILED); } else { SET_CLASS_STATE(CSTATE_COMPLETE); } /* Since we'll never run this again we might as well * lose it now. However, if there was an exception, keep * it so the stack trace doesn't lose the <clinit> frame. */#if defined(TRANSLATOR) && (defined (MD_UNREGISTER_JIT_EXCEPTION_INFO) || defined (JIT3))#if defined(MD_UNREGISTER_JIT_EXCEPTION_INFO) if (exc == 0) { MD_UNREGISTER_JIT_EXCEPTION_INFO (getMethodCodeStart(meth), METHOD_NATIVECODE(meth), meth->c.ncode.ncode_end); }#endif#endif if (#if defined(JIT3) (exc == 0) &&#endif#if defined(KAFFE_XPROFILER) !xProfFlag &&#endif 1) { _SET_METHOD_NATIVECODE(meth, NULL); setMethodCodeStart(meth, NULL); meth->c.ncode.ncode_end = NULL; } }done: /* If anything ever goes wrong with this class, we declare it dead * and will respond with NoClassDefFoundErrors to any future attempts * to access that class. * NB: this does not include when a static initializer failed. */ if (success == false && class->state != CSTATE_FAILED) { SET_CLASS_STATE(CSTATE_FAILED); if( ce->state != NMS_DONE ) { setClassMappingState(ce, NMS_EMPTY); } } /* wake up any waiting threads */ broadcastOnClass(class); unlockClass(class);DBG(RESERROR, for (i = 0; i < depth; dprintf(" "), i++); depth--; dprintf("%p leaving process class %s -> %s\n", KTHREAD(current)(), class->name->data, success ? "success" : "failure"); ); return (success);}static intexpandMethods(Hjava_lang_Class *cl, Method *imeth, errorInfo *einfo){ Method *new_methods = NULL; int retval = 0; /* if( !CLASS_IS_ABSTRACT(cl) ) { postExceptionMessage(einfo, JAVA_LANG(ClassFormatError), "(class: %s, method: %s signature: %s) " "Abstract method in non-abstract class", cl->name->data, imeth->name->data, imeth->parsed_sig->signature->data); } else */ if( (new_methods = gc_realloc(Kaffe_get_class_methods(cl), sizeof(Method) * (CLASS_NMETHODS(cl) + 1), KGC_ALLOC_METHOD)) ) { int i; i = CLASS_NMETHODS(cl); Kaffe_set_class_methods(cl, new_methods); utf8ConstAddRef(imeth->name); new_methods[i] = *imeth; /* Allocate a new parsed_signature_t for the method. We can't use the one * of the implemented method as destroyClass would then try to free it * twice. */ new_methods[i].parsed_sig = duplicateParsedSignature (imeth->parsed_sig, einfo); if (new_methods[i].parsed_sig == NULL) { gc_free (new_methods); return 0; } new_methods[i].ndeclared_exceptions = -1; new_methods[i].declared_exceptions_u.remote_exceptions = imeth; new_methods[i].class = cl; CLASS_NMETHODS(cl) = i + 1; retval = 1; } else { gc_free(new_methods); postOutOfMemory(einfo); } return( retval );}static intexpandInterfaces(Hjava_lang_Class *root_class, Hjava_lang_Class *class, errorInfo *einfo){ int i, j, k, success = 1; /* * Check to make sure all the interface methods are implemented, * otherwise, we'll need to add a slot. */ for( i = 0; (i < class->interface_len) && success; i++ ) { Hjava_lang_Class *iface; iface = class->interfaces[i]; if( !expandInterfaces(root_class, iface, einfo) ) { success = 0; break; } for( j = 0; (j < CLASS_NMETHODS(iface)) && success; j++ ) { Hjava_lang_Class *cl; int foundit = 0; Method *imeth; imeth = &(Kaffe_get_class_methods(iface)[j]); /* Igore statics */ if( imeth->accflags & ACC_STATIC ) continue; /* Search for the corresponding slot. */ for( cl = root_class; cl && !foundit; cl = cl->superclass ) { for( k = 0; k < CLASS_NMETHODS(cl); k++ ) { Method *cmeth; cmeth = &(Kaffe_get_class_methods(cl)[k]); if( (cmeth->name == imeth->name) && (cmeth->parsed_sig->signature == imeth->parsed_sig->signature) ) { foundit = 1; break; } } } if( !foundit ) { /* No impl, add a slot */ success = expandMethods(root_class, imeth, einfo); } } } return( success );}static boolresolveInterfaces(Hjava_lang_Class *class, errorInfo *einfo){ int i, j, k; int totalilen; Hjava_lang_Class** newifaces; Hjava_lang_Class* nclass; bool success = true; /* optimistic */ /* Load all the implemented interfaces. */ j = class->interface_len; nclass = class->superclass; if (nclass != 0 && nclass != ObjectClass) { /* If class is an interface, its superclass must * be java.lang.Object or the class file is broken. */ if (CLASS_IS_INTERFACE(class)) { postException(einfo, JAVA_LANG(VerifyError)); success = false; goto done; } j += getSuperclass(class)->total_interface_len; } for (i = 0; i < class->interface_len; i++) { uintp iface = (uintp)class->interfaces[i]; unlockClass(class);#if defined(HAVE_GCJ_SUPPORT) if (CLASS_GCJ(class)) { nclass = gcjGetClass((void*)iface, einfo); } else { nclass = getClass(iface, class, einfo); }#else nclass = getClass(iface, class, einfo);#endif /* HAVE_GCJ_SUPPORT */ class->interfaces[i] = nclass; lockClass(class); if (class->interfaces[i] == 0) { success = false; goto done; } if (!(class->interfaces[i]->accflags & ACC_INTERFACE)) { postExceptionMessage( einfo, JAVA_LANG(IncompatibleClassChangeError), "Class, %s, used as interface by %s", class->interfaces[i]->name->data, class->name->data); success = false; goto done; } if (instanceof(class, class->interfaces[i])) { postExceptionMessage( einfo, JAVA_LANG(ClassCircularityError), "%s", class->name->data); success = false; goto done; } j += class->interfaces[i]->total_interface_len; } totalilen = j; /* We build a list of *all* interfaces this class can use */ if (class->interface_len != j) { newifaces = (Hjava_lang_Class**)gc_malloc(sizeof(Hjava_lang_Class**) * j, KGC_ALLOC_INTERFACE); if (newifaces == 0) { postOutOfMemory(einfo); success = false; goto done; } for (i = 0; i < class->interface_len; i++) { newifaces[i] = class->interfaces[i]; } nclass = class->superclass; if (nclass != 0 && nclass != ObjectClass) { for (j = 0; j < nclass->total_interface_len; j++, i++) { newifaces[i] = nclass->interfaces[j]; } } for (k = 0; k < class->interface_len; k++) { nclass = class->interfaces[k]; for (j = 0; j < nclass->total_interface_len; j++, i++) { newifaces[i] = nclass->interfaces[j]; } } if (class->interfaces != NULL) gc_rm_ref(class->interfaces); class->interfaces = newifaces; if (!gc_add_ref(class->interfaces)) { postOutOfMemory(einfo); success = false; goto done; } } /* don't set total_interface_len before interfaces to avoid * having walkClass attempting to walk interfaces */ class->total_interface_len = totalilen; if( !CLASS_IS_INTERFACE(class) ) { success = expandInterfaces(class, class, einfo); }done: return (success);}/** * Check if a class name is in a set of packages. * * XXX Move somewhere else... * * @param plist The null terminated list of packages to check against. * @param name The class name to check. * @return True if the class name is in one of the packages, false otherwise. */static intinPackageSet(const char **plist, Utf8Const *name){ unsigned int name_len, lpc, retval = 0; name_len = strlen(name->data); for( lpc = 0; plist[lpc] && !retval; lpc++ ) { unsigned int len; len = strlen(plist[lpc]); if( (name_len > len) && strncmp(name->data, plist[lpc], len) == 0 ) { retval = 1; } } return( retval );}/** * The set of restricted packages that a user defined class loader can't add * classes to. */static const char *restrictedPackages[] = { "java/", "kaffe/", NULL};static intinternalSetupClass(Hjava_lang_Class* cl, Utf8Const* name, int flags, int this_index, int su, Hjava_lang_ClassLoader* loader, struct _errorInfo *einfo){ if( (loader != NULL) && inPackageSet(restrictedPackages, name) ) { /* * Can't allow users to add classes to the bootstrap * packages. */ postExceptionMessage(einfo, JAVA_LANG(SecurityException), "Prohibited package: %s", name->data); return 0; } if( cl->name == NULL ) { utf8ConstAssign(cl->name, name); } else if( !utf8ConstEqual(cl->name, name) ) { postExceptionMessage(einfo, JAVA_LANG(ClassFormatError), "%s (wrong name: %s)", name->data, cl->name->data); return 0; } cl->packageLength = findPackageLength(name->data); Kaffe_set_class_methods(cl, NULL); CLASS_NMETHODS(cl) = 0; assert(cl->superclass == 0); cl->superclass = (Hjava_lang_Class*)(uintp)su; cl->msize = 0; CLASS_FIELDS(cl) = NULL; CLASS_FSIZE(cl) = 0; cl->accflags = flags; cl->vtable = NULL; cl->interfaces = NULL; cl->interface_len = 0; assert(cl->state < CSTATE_LOADED); cl->state = CSTATE_LOADED; cl->loader = loader; cl->this_index = this_index; cl->inner_classes = NULL; cl->nr_inner_classes = 0; cl->this_inner_index = -1; /* set protection domain to the default */ if (loader == NULL) { cl->protectionDomain = defaultProtectionDomain; } return 1;}Hjava_lang_Class*setupClass(Hjava_lang_Class* cl, constIndex c, constIndex s, u2 flags, Hjava_lang_ClassLoader* loader, errorInfo* einfo){ constants* pool; pool = CLASS_CONSTANTS(cl); /* Find the name of the class */ if (c >= CLASS_CONST_SIZE (cl) || pool->tags[c] != CONSTANT_Class) { postExceptionMessage(einfo, JAVA_LANG(ClassFormatError), "this class constant pool index is bogus"); return (NULL); } if (!internalSetupClass(cl, WORD2UTF(pool->data[c]), flags, c, s, loader, einfo)) return (NULL); return (cl);}/* * add source file name to be printed in exception backtraces */booladdSourceFile(Hjava_lang_Class* c, int idx, errorInfo *einfo){ constants* pool; const char* sourcefile; const char* basename; bool success = true; pool = CLASS_CONSTANTS (c); if (pool->tags[idx] != CONSTANT_Utf8) { postExceptionMessage(einfo, JAVA_LANG(ClassFormatError), "invalid sourcefile index: %d", idx); return false; } sourcefile = WORD2UTF (pool->data[idx])->data; basename = strrchr(sourcefile, '/'); if (basename == 0) { basename = sourcefile; } else { basename++; } c->sourcefile = gc_malloc(strlen(basename) + 1, KGC_ALLOC_CLASSMISC); if (c->sourcefile != 0) { strcpy(c->sourcefile, basename); } else { success = false; postOutOfMemory(einfo); } /* we should be able to drop this utf8 here */ utf8ConstRelease(WORD2UTF (pool->data[idx])); pool->data[idx] = 0; return (success);}/* * Read in InnerClasses declares for a class */booladdInnerClasses(Hjava_lang_Class* c, size_t len UNUSED, classFile* fp, errorInfo *einfo){ int i; u2 nr; innerClass *ic; if (! checkBufSize(fp, 2, CLASS_CNAME(c), einfo)) return false;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?