📄 class.c
字号:
/*========================================================================= * System-level constructors *=======================================================================*//*========================================================================= * FUNCTION: InitializeJavaSystemClasses() * TYPE: private constructor * OVERVIEW: Load the standard Java system classes needed by the VM. * INTERFACE: * parameters: <none> * returns: <nothing> *=======================================================================*/void InitializeJavaSystemClasses(){ /* This just creates empty structures that will eventually be filled in. * The magic numbers are the lengths of the strings. * The order is slightly important. * JavaLangObject has to be created before the array classes * These four classes have to be created before anything is loaded. */#if !ROMIZING int i; JavaLangObject = (INSTANCE_CLASS)getRawClass("java/lang/Object"); JavaLangClass = (INSTANCE_CLASS)getRawClass("java/lang/Class"); JavaLangString = (INSTANCE_CLASS)getRawClass("java/lang/String"); memset(PrimitiveArrayClasses, 0, sizeof(PrimitiveArrayClasses)); for (i = T_FIRSTPRIMITIVE_TYPE; i <= T_LASTPRIMITIVETYPE; i++) { if (!IMPLEMENTS_FLOAT && (i == T_FLOAT || i == T_DOUBLE)) { /* If we're not implementing floats, then don't try to * create arrays of floats or arrays of doubles */ } else { PrimitiveArrayClasses[i] = getArrayClass(1, NULL, typeCodeToSignature((char)i)); } } /* Now we can go back and create these for real. . . .*/ loadClassfile(JavaLangObject, TRUE); loadClassfile(JavaLangClass, TRUE); loadClassfile(JavaLangString, TRUE); /* Load or initialize some other classes */ JavaLangSystem = (INSTANCE_CLASS)getClass("java/lang/System"); JavaLangThread = (INSTANCE_CLASS)getClass("java/lang/Thread"); JavaLangThrowable = (INSTANCE_CLASS)getClass("java/lang/Throwable"); JavaLangError = (INSTANCE_CLASS)getClass("java/lang/Error"); if (INCLUDEDEBUGCODE) { if ( (JavaLangObject->status == CLASS_ERROR) || (JavaLangClass->status == CLASS_ERROR) || (JavaLangString->status == CLASS_ERROR) || (JavaLangThread == NULL) || (JavaLangThrowable == NULL) || (JavaLangError == NULL)) { fatalVMError(KVM_MSG_UNABLE_TO_INITIALIZE_SYSTEM_CLASSES); } }#else InitializeROMImage();#endif /* !ROMIZING */ if (!ROMIZING || RELOCATABLE_ROM) { initNameAndType = getNameAndTypeKey("<init>", "()V"); clinitNameAndType = getNameAndTypeKey("<clinit>", "()V"); runNameAndType = getNameAndTypeKey("run", "()V"); mainNameAndType = getNameAndTypeKey("main", "([Ljava/lang/String;)V"); /* Get pointers to the special methods. CustomCode isn't used yet, * but probably will be in the future */ RunCustomCodeMethod = getSpecialMethod(JavaLangClass, getNameAndTypeKey("runCustomCode", "()V")); /* patch the bytecode, was a "return" */ if (RELOCATABLE_ROM) { /* Do nothing. Already patched */ } else if (!USESTATIC || (inAnyHeap(RunCustomCodeMethod->u.java.code))){ RunCustomCodeMethod->u.java.code[0] = CUSTOMCODE; RunCustomCodeMethod->u.java.maxStack = RunCustomCodeMethod_MAX_STACK_SIZE; } else { BYTE newcode = CUSTOMCODE; short newMaxStack = RunCustomCodeMethod_MAX_STACK_SIZE; char *start = (char*)((INSTANCE_CLASS)JavaLangClass)->constPool; int offset = (char*)(RunCustomCodeMethod->u.java.code) - start; modifyStaticMemory(start, offset, &newcode, sizeof(newcode)); offset = (char *)(&RunCustomCodeMethod->u.java.maxStack) - start; modifyStaticMemory(start, offset, &newMaxStack, sizeof(newMaxStack)); } } JavaLangOutOfMemoryError = (INSTANCE_CLASS)getClass("java/lang/OutOfMemoryError"); OutOfMemoryObject = (THROWABLE_INSTANCE)instantiate(JavaLangOutOfMemoryError); makeGlobalRoot((cell **)&OutOfMemoryObject); StackOverflowObject = OutOfMemoryObject; makeGlobalRoot((cell **)&StackOverflowObject);}/*========================================================================= * FUNCTION: FinalizeJavaSystemClasses() * TYPE: private constructor * OVERVIEW: Perform any cleanup necessary so that the class files can * be run again. * INTERFACE: * parameters: <none> * returns: <nothing> *=======================================================================*/void FinalizeJavaSystemClasses(){ if (ROMIZING) { FinalizeROMImage(); FOR_ALL_CLASSES(clazz) /* Remove any class monitors */ if (OBJECT_HAS_MONITOR(clazz)) { clearObjectMonitor((OBJECT)clazz); } if (!IS_ARRAY_CLASS(clazz)) { /* Reset the state of the class to be its initial state. * The ACC_ROM_NON_INIT_CLASS says that neither this class nor * any of its superclasses has a <clinit> method */ INSTANCE_CLASS iclazz = ((INSTANCE_CLASS)clazz); setClassInitialThread(iclazz, NULL); setClassStatus(iclazz, (iclazz->clazz.accessFlags & ACC_ROM_NON_INIT_CLASS) ? CLASS_READY : CLASS_VERIFIED); } END_FOR_ALL_CLASSES }}/*========================================================================= * Operations on classes *=======================================================================*//*========================================================================= * FUNCTION: getRawClass() * TYPE: instance-level operation on runtime classes * OVERVIEW: Find a class with the given name, or create an empty * stub for the class, if necessary. * INTERFACE: *=======================================================================*/CLASSgetRawClass(const char *name) { if (INCLUDEDEBUGCODE && inCurrentHeap(name)) { fatalError(KVM_MSG_BAD_CALL_TO_GETRAWCLASS); } return getRawClassX(&name, 0, strlen(name));}CLASSgetRawClassX(CONST_CHAR_HANDLE nameH, int offset, int length){ CLASS result; const char *start = unhand(nameH); const char *className = start + offset; const char *firstNonBracket, *p; int depth; /* Find the firstNonBracket character, and the last slash in the string */ for (p = className; *p == '['; p++) {}; firstNonBracket = p; depth = p - className; if (depth == 0) { UString packageName, baseName; for (p = className + length ; ;) { --p; if (*p == '/') { int packageNameLength = p - className; int baseNameLength = (length - 1) - packageNameLength; packageName = getUStringX(nameH, offset, packageNameLength); /* p and start may no longer be valid pointers, but there * difference is still a valid offset */ baseName = getUStringX(nameH, (p + 1) - start, baseNameLength); break; } else if (p == className) { packageName = NULL; baseName = getUStringX(nameH, offset, length); break; } } result = change_Name_to_CLASS(packageName, baseName); return result; } else if (depth + 1 == length) { /* An array of some primitive type */ return (CLASS)getArrayClass(depth, NULL, *firstNonBracket); } else { INSTANCE_CLASS baseClass; const char *baseClassStart = firstNonBracket + 1; /* skip the 'L' */ const char *baseClassEnd = className + length - 1; /* skip final ';' */ baseClass = (INSTANCE_CLASS) getRawClassX(nameH, baseClassStart - start, baseClassEnd - baseClassStart); /* The call to getArrayClass but we don't have any pointers any more. */ return (CLASS)getArrayClass(depth, baseClass, '\0'); }}/*========================================================================= * FUNCTION: getClass() * TYPE: public instance-level operation on runtime classes * OVERVIEW: Find a class with the given name, loading the class * if necessary. * INTERFACE: * parameters: class name as a string * returns: class pointer or NIL if not found * * NOTE: This operation may load new classes into the system. * Since class loading may necessitate the execution * of class initialization methods (<clinit> methods), * hence requiring the invocation of the bytecode interpreter, * we must be careful not to mess the native (C/C++) call * stack. *=======================================================================*/CLASSgetClass(const char *name) { if (INCLUDEDEBUGCODE && inCurrentHeap(name)) { fatalError(KVM_MSG_BAD_CALL_TO_GETCLASS); } return getClassX(&name, 0, strlen(name));}CLASSgetClassX(CONST_CHAR_HANDLE nameH, int offset, int length){ CLASS clazz; clazz = getRawClassX(nameH, offset, length); if (!IS_ARRAY_CLASS(clazz)) { if (((INSTANCE_CLASS)clazz)->status == CLASS_RAW) { loadClassfile((INSTANCE_CLASS)clazz, FALSE); } if (((INSTANCE_CLASS)clazz)->status == CLASS_ERROR) { return NULL; } } return clazz;}/*========================================================================= * FUNCTION: getArrayClass() * TYPE: private helper function * OVERVIEW: Create an array class. * INTERFACE: * arguments: depth: depth of the new array * baseClass: if the base type is a class this is nonNull and * contains the base type * signCode: if the base type is a primitive type, then * baseClass must be NULL, and this contains the * letter representing the base type. * parameters: result: class pointer. *=======================================================================*/ARRAY_CLASSgetArrayClass(int depth, INSTANCE_CLASS baseClass, char signCode){ UString packageName, baseName; bool_t isPrimitiveBase = (baseClass == NULL); ARRAY_CLASS clazz, result;#if ENABLE_JAVA_DEBUGGER bool_t needEvent = FALSE;#endif if (isPrimitiveBase) { const char *temp = str_buffer; packageName = NULL; memset(str_buffer, '[', depth); str_buffer[depth] = signCode; baseName = getUStringX(&temp, 0, depth + 1); } else { memset(str_buffer, '[', depth); sprintf(str_buffer + depth, "L%s;", UStringInfo(baseClass->clazz.baseName)); baseName = getUString(str_buffer); packageName = baseClass->clazz.packageName; } result = (ARRAY_CLASS)change_Name_to_CLASS(packageName, baseName);#if ENABLE_JAVA_DEBUGGER if (result->clazz.ofClass == NULL) needEvent = TRUE;#endif for (clazz = result; clazz->clazz.ofClass == NULL; ) { /* LOOP ASSERT: depth is the array depth of "clazz" */ /* This clazz is newly created. We need to fill in info. We * may need to iterate, since this class's element type may also need * to be be created */ clazz->clazz.ofClass = JavaLangClass; if (depth == 1 && isPrimitiveBase) {#if ROMIZING fatalError(KVM_MSG_CREATING_PRIMITIVE_ARRAY);#else char typeCode; switch(signCode) { case 'C' : typeCode = T_CHAR ; break; case 'B' : typeCode = T_BYTE ; break; case 'Z' : typeCode = T_BOOLEAN ; break;#if IMPLEMENTS_FLOAT case 'F' : typeCode = T_FLOAT ; break; case 'D' : typeCode = T_DOUBLE ; break;#endif /* IMPLEMENTS_FLOAT */ case 'S' : typeCode = T_SHORT ; break; case 'I' : typeCode = T_INT ; break; case 'J' : typeCode = T_LONG ; break; case 'V' : typeCode = T_VOID ; break; case 'L' : typeCode = T_CLASS ; break; default : fatalVMError(KVM_MSG_BAD_SIGNATURE); typeCode = 0; } clazz->gcType = GCT_ARRAY; clazz->itemSize = arrayItemSize(typeCode); clazz->u.primType = typeCode; clazz->clazz.accessFlags = ACC_FINAL | ACC_ABSTRACT | ACC_PUBLIC | ACC_ARRAY_CLASS; clazz->clazz.key = signCode + (short)(1 << FIELD_KEY_ARRAY_SHIFT); /* All finished */#endif /* ROMIZING */ break; } else { clazz->gcType = GCT_OBJECTARRAY; clazz->itemSize = arrayItemSize(T_REFERENCE); if (isPrimitiveBase) { clazz->clazz.accessFlags = ACC_FINAL | ACC_ABSTRACT | ACC_PUBLIC | ACC_ARRAY_CLASS; } else if (baseClass->status >= CLASS_LOADED) { clazz->clazz.accessFlags = ACC_FINAL | ACC_ABSTRACT | ACC_ARRAY_CLASS | (baseClass->clazz.accessFlags & ACC_PUBLIC); } else { clazz->clazz.accessFlags = ACC_FINAL | ACC_ABSTRACT | ACC_ARRAY_CLASS; clazz->flags = ARRAY_FLAG_BASE_NOT_LOADED; } if (depth >= MAX_FIELD_KEY_ARRAY_DEPTH) { clazz->clazz.key |= (MAX_FIELD_KEY_ARRAY_DEPTH << FIELD_KEY_ARRAY_SHIFT); } else if (isPrimitiveBase) { clazz->clazz.key = (depth << FIELD_KEY_ARRAY_SHIFT) + signCode; } else { clazz->clazz.key = (depth << FIELD_KEY_ARRAY_SHIFT) + baseClass->clazz.key; } if (depth == 1) { /* We must be nonPrimitive. primitive was handled above */ clazz->u.elemClass = (CLASS)baseClass; /* All finished */ break; } else { /* Class of depth > 1. */ UString thisBaseName = clazz->clazz.baseName; const char *baseName = UStringInfo(thisBaseName); UString subBaseName = getUStringX(&baseName, 1, thisBaseName->length - 1); CLASS elemClass = change_Name_to_CLASS(packageName, subBaseName); clazz->u.elemClass = elemClass; /* Now "recurse" on elemClass, initialized it, */ /* also, if necessary */ clazz = (ARRAY_CLASS)elemClass; depth--; continue; } } }#if ENABLE_JAVA_DEBUGGER if (vmDebugReady && needEvent) { CEModPtr cep = GetCEModifier(); cep->loc.classID = GET_CLASS_DEBUGGERID(&result->clazz); cep->threadID = getObjectID((OBJECT)CurrentThread->javaThread); cep->eventKind = JDWP_EventKind_CLASS_PREPARE; insertDebugEvent(cep); }#endif /* ENABLE_JAVA_DEBUGGER */ return result;}/*========================================================================= * FUNCTION: getObjectArrayClass * TYPE: public instance-level operation on runtime classes * OVERVIEW: Creates an array class whose elements are the specified type * getObjectArrayClass expects an array or instance Class * INTERFACE: * parameters: see above * returns: class pointer *=======================================================================*/ARRAY_CLASSgetObjectArrayClass(CLASS clazz) { CLASS subClass = clazz;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -