classcreate.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 2,007 行 · 第 1/5 页
C
2,007 行
/* * Fix for 4490166: Check if the array class is already defined in the * defining class loader of the element class before creating one. * We need this step since we don't perform CVMclassLoadClass() * against an array class directly. */ if (arrayLoader != loader) { /* Need to lock the arrayLoader too */ if (arrayLoader == NULL) { CVM_NULL_CLASSLOADER_LOCK(ee); } else { if (!CVMgcSafeObjectLock(ee, arrayLoader)) { CVMthrowOutOfMemoryError(ee, NULL); return NULL; } } arrayCb = CVMclassLookupByTypeFromClassLoader(ee, arrayTypeId, CVM_FALSE, arrayLoader, pd, CVM_FALSE); if (arrayCb != NULL) { /* Found the array class */ goto finish; } else { CVMClassBlock* classNotFoundCb = CVMsystemClass(java_lang_ClassNotFoundException); CVMClassBlock* noClassDefFoundCb = CVMsystemClass(java_lang_NoClassDefFoundError); CVMClassBlock* exceptionCb; CVMID_objectGetClass(ee, CVMlocalExceptionICell(ee), exceptionCb); if (CVMisSubclassOf(ee, exceptionCb, classNotFoundCb) || CVMisSubclassOf(ee, exceptionCb, noClassDefFoundCb)) { /* Not loaded yet. Clear the error and keep going */ CVMclearLocalException(ee); } else { /* Critical error must have occurred. Discontinue the work */ goto finish; } } } /* * Allocate memory for the array class. */ arrayCb = (CVMClassBlock*) calloc(1, sizeof(CVMClassBlock) + sizeof(CVMArrayInfo)); if (arrayCb == NULL) { CVMthrowOutOfMemoryError(ee, NULL); goto finish; } CVMcbArrayInfo(arrayCb) = (CVMArrayInfo*)(arrayCb + 1); /* Must be done before calling CVMarrayXXX macros to avoid asserts. */ CVMcbClassName(arrayCb) = CVMtypeidCloneClassID(ee, arrayTypeId ); /* * Two cases. The new CVMArrayInfo is formed differently in each case. * * 1) The element type is an array. * 2) The element type is a class. * * This function does not make arrays of basic types. Those are romized. */ CVMassert(!CVMcbIs(elemCb, PRIMITIVE)); if (CVMtypeidIsArray(CVMcbClassName(elemCb))) { /* * And now, make up the details of the array info struct * for the new array class. */ CVMarrayDepth(arrayCb) = CVMarrayDepth(elemCb) + 1; CVMarrayBaseType(arrayCb) = CVMarrayBaseType(elemCb); CVMarrayBaseCb(arrayCb) = CVMarrayBaseCb(elemCb); } else { /* * elemCb must be a class (it can't be a basic type, since * we already have the array classes of basic types stashed * away in CVMbasicTypeArrayClassblocks[]) */ /* * And now, make up the details of the fake constant pool * for the new array */ CVMarrayDepth(arrayCb) = 1; CVMarrayBaseType(arrayCb) = CVM_T_CLASS; CVMarrayBaseCb(arrayCb) = elemCb; } CVMarrayElementCb(arrayCb) = elemCb; /* * Fill in the other details */ CVMcbGcMap(arrayCb).map = CVM_GCMAP_ALLREFS_FLAG; /* No basic type arrays! */ CVMcbSuperclass(arrayCb) = (CVMClassBlock*)CVMsystemClass(java_lang_Object); CVMcbInterfaces(arrayCb) = CVMcbInterfaces(CVMsystemClass(java_lang_Object)); /* not in ROM, no <clinit> nor statics */ CVMassert(!CVMcbIsInROM(arrayCb)); CVMassert(!CVMcbHasStaticsOrClinit(arrayCb)); /* * We are as public as our element class */ elemClassAccess = CVMcbIs(elemCb, PUBLIC); CVMcbAccessFlags(arrayCb) = elemClassAccess | CVM_CLASS_ACC_ABSTRACT | CVM_CLASS_ACC_FINAL; CVMcbRuntimeFlags(arrayCb) = CVM_CLASS_SUPERCLASS_LOADED | CVM_CLASS_LINKED | CVM_CLASS_VERIFIED; CVMcbSetInitializationDoneFlag(ee, arrayCb); /* * Use the java/lang/Object method table */ CVMcbMethodTablePtr(arrayCb) = CVMcbMethodTablePtr(CVMsystemClass(java_lang_Object)); CVMcbMethodTableCount(arrayCb) = CVMcbMethodTableCount(CVMsystemClass(java_lang_Object)); /* * Create the Java side "mirror" to this class */ arrayClass = CVMclassCreateJavaInstance(ee, arrayCb, arrayLoader); if (arrayClass == NULL) { /* free everything and return */ free(arrayCb); arrayCb = NULL; goto finish; }#ifdef CVM_CLASSLOADING CVMcbClassLoader(arrayCb) = arrayLoader;#endif /* * Add the class to our class database and let the class loader know * about the class. */ if (!CVMclassAddToLoadedClasses(ee, arrayCb, arrayClass)) { /* * If CVMcbJavaInstance() is still NULL, then the new Class * global root was never setup, which means we are responsible for * freeing the class. */ if (CVMcbJavaInstance(arrayCb) == NULL) { free(arrayCb); } arrayCb = NULL; /* exception already thrown */ goto finish; } /* * After this point, if there is a failure then the class will get * freed when it is gc'd. This will happen very shortly since * there will be no class global root or ClassLoader instance * refering to the class. */ /* Add to the loader cache. */ if (!CVMloaderCacheAdd(ee, arrayCb, CVMcbClassLoader(arrayCb))) { arrayCb = NULL; /* exception already thrown */ goto finish; } #ifdef CVM_CLASSLOADING /* * Call ClassLoader.addClass() to add to the ClassLoader's * database of classes. */ if (CVMcbClassLoader(arrayCb) != NULL) { JNIEnv* env = CVMexecEnv2JniEnv(ee); /* We need a JNI local frame so we can make a JNI method call. */ if (CVMjniPushLocalFrame(env, 1) == JNI_OK) { (*env)->CallVoidMethod(env, CVMcbClassLoader(arrayCb), CVMglobals.java_lang_ClassLoader_addClass, arrayClass); CVMjniPopLocalFrame(env, NULL); } if (CVMlocalExceptionOccurred(ee)) { /* make sure a loaderCache lookup will fail */ CVMcbSetErrorFlag(ee, arrayCb); CVMcbClearRuntimeFlag(arrayCb, ee, SUPERCLASS_LOADED); arrayCb = NULL; /* exception already thrown */ goto finish; } }#endif CVMtraceClassLoading(("CL: Created array cb=0x%x <%!C>\n", arrayCb, arrayTypeId));#ifdef CVM_JVMPI /* * JVMPI is notified of other class load events in * java.lang.Class.notifyClassLoaded. But that never * gets called for arrays, so we do it here. */ if (CVMjvmpiEventClassLoadIsEnabled()) { CVMjvmpiPostClassLoadEvent(ee, arrayCb); }#endif /* CVM_JVMPI */ finish: if (arrayLoader != loader) { /* Need to unlock the arrayLoader */ if (arrayLoader == NULL) { CVM_NULL_CLASSLOADER_UNLOCK(ee); } else { CVMBool success = CVMgcSafeObjectUnlock(ee, arrayLoader); CVMassert(success); (void) success; } } /* * We can free the arrayClass root that was being used to keep the * Class instance alive. If there was a failure, then this will allow * the Class to be gc'd. If there wasn't a failure, then calling * ClassLoader.addClass() will keep the class alive. */ if (arrayClass != NULL) { CVMID_freeGlobalRoot(ee, arrayClass); arrayClass = NULL; } return arrayCb;}/* * CVMclassCreateMultiArrayClass - creates the specified array class by * iteratively (i.e. non-recursively) creating all the layers of the array * class from the inner most to the outer most. Needed for any array class * type that wasn't reference by romized code and we make a reference to it * at runtime. */CVMClassBlock*CVMclassCreateMultiArrayClass(CVMExecEnv* ee, CVMClassTypeID arrayTypeId, CVMClassLoaderICell* loader, CVMObjectICell* pd){ int outerDepth = 0; CVMClassBlock *arrayCb = NULL; CVMClassTypeID currentTypeID = arrayTypeId; CVMClassTypeID elemTypeID; CVMBool currentTypeIDWasAcquired = CVM_FALSE; int i; CVMassert(CVMtypeidIsArray(arrayTypeId)); /* Count the array layers that haven't been loaded yet. We start from the outer most until we get to an array element that has been loaded or an array element that is not an array type. We can assume that at least one layer isn't loaded yet (regardless of whether it is or not). CVMclassCreateArrayClass() will do the real work of loading the array class later, and will be called once for each layer that we counted. In the case that we only counted one layer, we'll call CVMclassCreateArrayClass() only once, and it will take care of loading the array (if it hasn't already been loaded) where its element is guaranteed to either have already been loaded, or is a non-array type. The guarantee comes from our pre-counting the number of layers that need to be loaded, and doing the loading from the innermost layer to the outermost. */ while (CVM_TRUE) { elemTypeID = CVMtypeidIncrementArrayDepth(ee, currentTypeID , -1); outerDepth++; /* If the element is also an array, then keep probing. Otherwise, we need to load it using the normal path: */ if (CVMtypeidIsArray(elemTypeID)) { CVMClassBlock *elemCb = NULL; /* The element of the current type is also an array. Look it up: */ if (loader == NULL || CVMtypeidIsPrimitive(CVMtypeidGetArrayBasetype(elemTypeID))) { elemCb = CVMpreloaderLookupFromType(ee, elemTypeID, NULL); } if (elemCb == NULL) { CVM_LOADERCACHE_LOCK(ee); elemCb = CVMloaderCacheLookup(ee, elemTypeID, loader); CVM_LOADERCACHE_UNLOCK(ee); } /* If we've found the element cb, then we're done because we can start building the array layers from there: */ if (elemCb != NULL) { break; } } else { /* If we get here, then we've peeled the layers down to a single dimensional array (we have reached the non-array element here). We can start building the array layers from here: */ break; } /* If we get here, then the element isn't loaded yet and is not a single dimension array. Let's see if the element's element has been loaded yet. Set prepare to repeat this loop for element layer. */ /* If the previous currentTypeID is one that we acquired using CVMtypeidIncrementArrayDepth() above, then we need to dispose of it before losing track of it: */ if (currentTypeIDWasAcquired) { CVMtypeidDisposeClassID(ee, currentTypeID); } /* Prepare to inspect the next inner level of array type: */ currentTypeID = elemTypeID; currentTypeIDWasAcquired = CVM_TRUE; } /* We have to dispose of the last elemTypeID that we acquired above using CVMtypeidIncrementArrayDepth(): */ CVMtypeidDisposeClassID(ee, elemTypeID); for (i = 0; i < outerDepth; i++) { CVMClassTypeID newTypeID; arrayCb = CVMclassCreateArrayClass(ee, currentTypeID, loader, pd); /* If we fail to load the element, then something wrong must have happened (e.g. an OutOfMemoryError): */ if (arrayCb == NULL) { break; } /* If we've just loaded the requested array type, then we're done. Skip the typeid work below: */ if (currentTypeID == arrayTypeId) { CVMassert(i == outerDepth - 1); break; } /* Prepare to load the next outer level of array type: */ newTypeID = CVMtypeidIncrementArrayDepth(ee, currentTypeID, 1); if (currentTypeIDWasAcquired) { CVMtypeidDisposeClassID(ee, currentTypeID); } currentTypeID = newTypeID; currentTypeIDWasAcquired = CVM_TRUE; } if (currentTypeIDWasAcquired) { CVMtypeidDisposeClassID(ee, currentTypeID); } return arrayCb;}/* * CVMclassCreateInternalClass - Creates a CVMClassBlock out of the * array of bytes passed to it. */#ifdef CVM_CLASSLOADING/* * CICcontext maintains our context while we parse the array of bytes. */typedef struct CICcontext CICcontext;struct CICcontext { const CVMUint8* ptr; const CVMUint8* end_ptr;#ifdef CVM_DEBUG_CLASSINFO const CVMUint8* mark;#endif jmp_buf jump_buffer; const char* classname; char* exceptionMsg; CVMClassBlock* exceptionCb; CVMClassICell* oldClassRoot; /* global root for the Class instance */ CVMClassBlock* cb; CVMConstantPool* cp; CVMConstantPool* utf8Cp; /* temporary cp for storing utf8 entries */ CVMUint16 major_version; CVMUint16 minor_version; int in_clinit; /* whether we are loading the <clinit> method */ /* * We keep track of 4 regions of memory: */ CVMUint8* intfSpace; /* CVMInterfaces */ CVMUint8* mainSpace; /* constant pool, methods, fields, and statics area */ CVMUint8* jmdSpace; /* CVMJavaMethodDescriptors */ CVMUint8* clinitJmdSpace; /* <clinit> CVMJavaMethodDescriptors */ CVMUint8* nextJmdSpace; /* next free byte in jmdSpace */#ifdef CVM_DEBUG CVMUint8* jmdSpaceLimit; CVMUint8* clinitJmdSpaceLimit;#endif CVMBool needsVerify; /*
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?