classcreate.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 2,007 行 · 第 1/5 页
C
2,007 行
/* * @(#)classcreate.c 1.195 06/10/25 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */#include "javavm/include/defs.h"#include "javavm/include/objects.h"#include "javavm/include/classes.h"#ifdef CVM_DUAL_STACK#include "javavm/include/dualstack_impl.h"#endif#include "javavm/include/limits.h"#include "javavm/include/common_exceptions.h"#include "javavm/include/typeid.h"#include "javavm/include/indirectmem.h"#include "javavm/include/interpreter.h"#include "javavm/include/localroots.h"#include "javavm/include/preloader.h"#include "javavm/include/globalroots.h"#include "javavm/include/globals.h"#include "javavm/include/utils.h"#include "javavm/include/stackmaps.h"#include "javavm/include/string.h"#include "javavm/include/packages.h"#include "javavm/include/verify.h"#include "javavm/export/jvm.h"#ifdef CVM_SPLIT_VERIFY#include "javavm/include/split_verify.h"#endif#ifdef CVM_JVMPI#include "javavm/include/jvmpi_impl.h"#endif#ifdef CVM_JVMTI#include "javavm/include/jvmtiExport.h"#endif#ifdef CVM_JIT#include "javavm/include/jit/jitmemory.h"#include "javavm/include/porting/jit/ccm.h"#endif#include "generated/offsets/java_lang_Class.h"#ifdef CVM_CLASSLOADING#include "generated/offsets/java_lang_ClassLoader.h"#include "generated/offsets/java_lang_Throwable.h"#endif#include "javavm/include/clib.h"#include "javavm/include/porting/ansi/setjmp.h"#include "javavm/include/porting/endianness.h"/* * align byte code * */#undef ALIGN_UP#undef ALIGN_NATURAL/* * Make sure that the whole expression is casted to CVMUint32. * Original code: * ((CVMUint32)((n) + ((align_grain) - 1)) & ~((align_grain)-1)) */#define ALIGN_UP(n,align_grain) \ (CVMUint32)(((n) + ((align_grain) - 1)) & ~((align_grain)-1))/* * A natural alignment is an alinment to the type CVMAddr which * is 4 byte on 32 bit platforms and 8 byte on 64 bit platforms. */#define ALIGN_NATURAL(p) \ (ALIGN_UP(p, sizeof(CVMAddr)))CVMClassICell*CVMdefineClass(CVMExecEnv* ee, const char *name, CVMClassLoaderICell* loader, const CVMUint8* buf, CVMUint32 bufLen, CVMObjectICell* pd, CVMBool isRedefine){#ifndef CVM_CLASSLOADING CVMthrowUnsupportedOperationException(ee, "Classloading not supported"); return NULL;#else CVMClassICell* classGlobalRoot; CVMObjectICell* resultCell; CVMObjectICell* pdCell; resultCell = CVMjniCreateLocalRef(ee); if (resultCell == NULL) { return NULL; /* exception already thrown */ } if (pd != NULL) { pdCell = CVMID_getProtectionDomainGlobalRoot(ee); if (pdCell == NULL) { CVMjniDeleteLocalRef(CVMexecEnv2JniEnv(ee), resultCell); CVMthrowOutOfMemoryError(ee, NULL); return NULL; } } else { pdCell = NULL; } classGlobalRoot = CVMclassCreateInternalClass(ee, buf, bufLen, loader, name, NULL, isRedefine); if (classGlobalRoot == NULL) { CVMjniDeleteLocalRef(CVMexecEnv2JniEnv(ee), resultCell); if (pdCell != NULL) { CVMID_freeProtectionDomainGlobalRoot(ee, pdCell); } return NULL; /* exception already thrown */ } { CVMClassBlock* cb = CVMgcSafeClassRef2ClassBlock(ee, classGlobalRoot); CVMcbProtectionDomain(cb) = pdCell; if (pdCell != NULL){ /* * Assign to this cell after assigning the cell to the cb * so that it gets scanned. Any earlier and there could be * a race. */ CVMID_icellAssign(ee, pdCell, pd); } } /* We must free the global root returned, but not until after we've * assigned it to another root to keep the Class alive until * Class.loadSuperClasses() is called. */ CVMID_icellAssign(ee, resultCell, classGlobalRoot); CVMID_freeGlobalRoot(ee, classGlobalRoot); return resultCell;#endif}/* * Create a java.lang.Class instance that corresponds to the new class cb. */static CVMClassICell*CVMclassCreateJavaInstance(CVMExecEnv* ee, CVMClassBlock* cb, CVMClassLoaderICell* loader){ CVMClassICell* classCell = CVMID_getGlobalRoot(ee); if (classCell == NULL) { CVMthrowOutOfMemoryError(ee, NULL); } else { CVMBool success; CVMD_gcUnsafeExec(ee, { CVMObject* newInstance = CVMgcAllocNewClassInstance(ee, cb); if (newInstance != NULL) { CVMID_icellSetDirect(ee, classCell, newInstance); /* Make sure the back-pointer is filled */ /* * cb is a native pointer (CVMClassBlock*) * therefore the cast has to be CVMAddr which is 4 byte on * 32 bit platforms and 8 byte on 64 bit platforms */ CVMassert(((CVMAddr*)newInstance)[CVMoffsetOfjava_lang_Class_classBlockPointer] == (CVMAddr)cb); if (loader != NULL) { CVMObject* directClassLoaderObj = CVMID_icellDirect(ee, loader); /* * Fill in the class loader field in the * java.lang.Class, so that keeping a Class alive * keeps its ClassLoader alive as well */ CVMD_fieldWriteRef(newInstance, CVMoffsetOfjava_lang_Class_loader, directClassLoaderObj); } } success = newInstance != NULL; }); if (!success) { CVMID_freeGlobalRoot(ee, classCell); CVMthrowOutOfMemoryError(ee, NULL); classCell = NULL; } } return classCell;}/* * CVMclassSetupClassLoaderRoot - silly function that is needed because * we can't put an #ifdef within an CVMD_gcUnsafeExec block. */static voidCVMclassSetupClassLoaderRoot(CVMExecEnv* ee, CVMClassBlock* cb, CVMClassLoaderICell* newClassLoaderRoot){#ifdef CVM_CLASSLOADING if (newClassLoaderRoot != NULL) { CVMcbClassLoader(cb) = newClassLoaderRoot; }#endif}/* * CVMclassAddToLoadedClasses - Add the class to our class databases. There * are 4 of them: * 1. classGlobalRoots - used by gc to keep all loaded classes live * when doing partial gc. * 2. class table - used by gc and jvmti. Akin to JDK bin_classes. * 3. loader cache - cache of <Class,ClassLoader> pairs used to speed * up class lookups. * 4. ClassLoader - each ClassLoader maintains a private database of * Classes it has loaded. This is needed to keep a Class live when * there is no instances of the Class and the ClassLoader is still * live. * However, (3) and (4) are deferred until after superclasses have * been loaded. See Class.loadSuperClasses(). */static CVMBoolCVMclassAddToLoadedClasses(CVMExecEnv* ee, CVMClassBlock* cb, CVMClassICell* oldClassRoot){ CVMClassICell* newClassRoot; CVMClassLoaderICell* newClassLoaderRoot; CVMClassBlock** classTableSlot = NULL; CVMBool result; /* * We make no attempt to keep gc from accessing the ClassLoader * global roots, Class global roots, or the class table while we * are allocating slots from them. It turns out that it is still * safe to allocate and free these resources while gc is accessing * them. The reason is because the cells are always empty while * they are being allocated or freed, so if gc does see one that * is the in process of being allocated or freed, it's just going * to ignore it anyway. */ /* * Get the ClassLoader global root to replace the root * currently stored in CVMcbClassLoader(). The CVMcbClassLoader() * root is not one we explicitly allocated. It either came from a * java stack frame or from the CVMcbClassLoader() field of * another loaded class. Because of this we don't need to worry * about deleting the original CVMcbClassLoader() root. */#ifndef CVM_CLASSLOADING newClassLoaderRoot = NULL;#else if (CVMcbClassLoader(cb) == NULL) { newClassLoaderRoot = NULL; } else { /* Get the current ClassLoader.loaderGlobalRoot field */ /* * Access member variable of type 'int' * and cast it to a native pointer. The java type 'int' only guarantees * 32 bit, but because one slot is used as storage space and * a slot is 64 bit on 64 bit platforms, it is possible * to store a native pointer without modification of * java source code. This assumes that all places in the C-code * which set/get this member are caught. */ CVMAddr temp; CVMID_fieldReadAddr(ee, CVMcbClassLoader(cb), CVMoffsetOfjava_lang_ClassLoader_loaderGlobalRoot, temp); newClassLoaderRoot = (CVMClassLoaderICell*)temp; }#endif /* * 1. Allocate a Class global root to replace the regular global * root currently keeping the Class instance live. Note that we must * hold onto the regular global root until after the new Class * global root has been assigned and the class loader has been * notified of the new class, or it may get gc'd. */ newClassRoot = CVMID_getClassGlobalRoot(ee); if (newClassRoot == NULL) { CVMthrowOutOfMemoryError(ee, NULL); goto done; /* exception already thrown */ } /* * 2. Allocate a class table slot. */ classTableSlot = CVMclassTableAllocateSlot(ee); if (classTableSlot == NULL) { CVMID_freeClassGlobalRoot(ee, newClassRoot); CVMthrowOutOfMemoryError(ee, NULL); goto done; /* exception already thrown */ } /* * We definitely need to do the following without fear that gc * will start up in the middle, because we will be in an inconsistent * state while doing the following assignments. This is why we got * all the allocations above out of the way first. */ CVMD_gcUnsafeExec(ee, { *classTableSlot = cb; CVMcbJavaInstance(cb) = newClassRoot; CVMID_icellAssignDirect(ee, newClassRoot, oldClassRoot); /* This is the starting point from which the Class object gets registered with the VM and special handling is required to GC it later: */ CVMglobals.gcCommon.classCreatedSinceLastGC = CVM_TRUE; CVMclassSetupClassLoaderRoot(ee, cb, newClassLoaderRoot); }); /* * 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. */ done: if (CVMlocalExceptionOccurred(ee)) { /* * We failed. If the Class global root was successfully allocated, * then the class will be gc'd and CVMclassFree() will handle the * cleanup. Otherwise, upon return it's up to the caller to handle * the cleanup. */ result = CVM_FALSE; } else { result = CVM_TRUE; } return result;}/* * CVMclassCreateArrayClass - creates a fake array class. Needed for any * array class type that wasn't reference by romized code and we make * a reference to it at runtime. */static CVMClassBlock*CVMclassCreateArrayClass(CVMExecEnv* ee, CVMClassTypeID arrayTypeId, CVMClassLoaderICell* loader, CVMObjectICell* pd){ CVMClassBlock* elemCb = NULL; CVMClassBlock* arrayCb; CVMUint32 elemClassAccess; CVMClassTypeID elementTypeID = CVMtypeidIncrementArrayDepth(ee, arrayTypeId, -1); CVMClassICell* arrayClass = NULL; CVMClassLoaderICell* arrayLoader; CVMtraceClassLoading(("CL: Creating array <%!C>\n", arrayTypeId)); /* * All primitive array types are part of the romized set so * we should never hit this assert. */ CVMassert(!CVMtypeidIsPrimitive(elementTypeID)); if (CVMtypeidIsArray(elementTypeID)) { /* * The element class is an array class, so lookup the array element * class. This may cause recursion back into CVMclassMakeArrayClass * if the element array class doesn't exists yet. */ /* %comment: c022 */ elemCb = CVMclassLookupByTypeFromClassLoader(ee, elementTypeID, CVM_FALSE, loader, pd, CVM_FALSE); } else { /* lookup the element class */ elemCb = CVMclassLookupByTypeFromClassLoader(ee, elementTypeID, CVM_FALSE, loader, pd, CVM_FALSE); } CVMtypeidDisposeClassID(ee, elementTypeID); if (elemCb == NULL) { return NULL; /* exception already thrown */ } /* * The "loader" passed in is the initiating ClassLoader. For here on * we want "loader" to be the ClassLoader of elemCb. */ arrayLoader = CVMcbClassLoader(elemCb);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?