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 + -
显示快捷键?