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