constantpool.c

来自「This is a resource based on j2me embedde」· C语言 代码 · 共 853 行 · 第 1/2 页

C
853
字号
/* * @(#)constantpool.c	1.53 06/10/22 * * 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.  * */#ifdef CVM_CLASSLOADING#include "javavm/include/interpreter.h"#include "javavm/include/classes.h"#include "javavm/include/utils.h"#include "javavm/include/common_exceptions.h"#include "javavm/include/globals.h"#include "javavm/include/indirectmem.h"/* * Resolve a NameAndType constant pool entry into an fb or mb. */static CVMFieldBlock*CVMcpResolveFieldref(CVMExecEnv* ee,		     CVMClassBlock* currentCb, 		     CVMConstantPool* cp, 		     CVMClassBlock* fieldCb,		     CVMUint16 typeIDIdx);static CVMMethodBlock*CVMcpResolveMethodref(CVMExecEnv* ee,		      CVMClassBlock* currentCb, 		      CVMConstantPool* cp, 		      CVMClassBlock* methodCb,		      CVMUint16 typeIDIdx);static CVMMethodBlock*CVMcpResolveInterfaceMethodref(CVMExecEnv* ee,			       CVMClassBlock* currentCb, 			       CVMConstantPool* cp, 			       CVMClassBlock* methodCb,			       CVMUint16 typeIDIdx);/* Iterate the class' constant pool and resolve unresolved entries. */voidCVMcpResolveCbEntriesWithoutClassLoading(CVMExecEnv* ee,                                          CVMClassBlock* cb){    CVMConstantPool* cp = CVMcbConstantPool(cb);    CVMUint16 i;    if ((cp != NULL) && (CVMcpTypes(cp) != NULL)) {        for (i = 1; i < CVMcbConstantPoolCount(cb); i++) {            CVMConstantPoolEntryType cpType = CVMcpEntryType(cp, i);            switch(cpType) {                case CVM_CONSTANT_ClassTypeID:                case CVM_CONSTANT_Fieldref:                case CVM_CONSTANT_Methodref:                case CVM_CONSTANT_InterfaceMethodref: {                    if (!CVMcpIsResolved(cp, i)) {                        CVMprivate_cpResolveEntryWithoutClassLoading(                            ee, cb, cp, i, NULL);                    }                    break;                }	        default:                    break;            }        }    }}/* * CVMcpResolveEntryWithoutClassLoading - resolves the specified cp entry, * but only if it can be done without causing any class loading. Returns * TRUE on success. If false is returned, then "p_typeid" will contain the * CVMMethodTypeID or CVMFieldTypeID of the entry if the entry is a MemberRef. * This is done because the typeID must be fetched while holding a lock. */CVMBoolCVMprivate_cpResolveEntryWithoutClassLoading(CVMExecEnv* ee,					     CVMClassBlock* currentCb, 					     CVMConstantPool* cp, 					     CVMUint16 cpIndex,					     CVMTypeID* p_typeid){    CVMClassTypeID  classID;/* id of the class referred to by the cp entry */    CVMConstantPoolEntryType cpType;    /*     * We need to make sure the cp entry is not resolved and get its     * contents while holding the lock. Otherwise it could get resolved     * after we do the check, but before we grab the entry, in which     * case the data we get is not what we expect.     */    CVMcpLock(ee);    cpType = CVMcpEntryType(cp, cpIndex);    if (cpType != CVM_CONSTANT_ClassTypeID && p_typeid != NULL) {	*p_typeid = CVM_TYPEID_ERROR;    }    if (CVMcpIsResolved(cp, cpIndex)) {	CVMcpUnlock(ee);	return CVM_TRUE; /* it's already resolved */#ifdef CVM_DUAL_STACK    } else if (CVMcpIsIllegal(cp, cpIndex)) {	CVMcpUnlock(ee);	return CVM_FALSE; /* it cannot be resolved */#endif    }    /*      * Get the classID of the class the entry refers to. This is key to     * how this function works. If the class that is referred to is      * already loaded, then we can resolve this entry without causing     * any class loading.     */    if (cpType == CVM_CONSTANT_ClassTypeID) {	classID = CVMcpGetClassTypeID(cp, cpIndex);	CVMassert(p_typeid == NULL);    } else {	CVMUint16 typeIDIdx;	CVMUint16 classCpIndex;	/* Get the classID of the class this entry refers to indirectly */	classCpIndex = CVMcpGetMemberRefClassIdx(cp, cpIndex);	if (!CVMcpIsResolved(cp, classCpIndex)) {	    classID = CVMcpGetClassTypeID(cp, classCpIndex);	} else {	    classID = CVM_TYPEID_ERROR;	}		/* also set p_typeid so we can return it to the caller if needed */	typeIDIdx = CVMcpGetMemberRefTypeIDIdx(cp, cpIndex);	if (p_typeid != NULL) {	    if (cpType == CVM_CONSTANT_Fieldref) {		*p_typeid = CVMcpGetFieldTypeID(cp, typeIDIdx);	    } else {		*p_typeid = CVMcpGetMethodTypeID(cp, typeIDIdx);	    }	}    }        /* We are all done accessing the constant pool, so we can unlock now */    CVMcpUnlock(ee);	    /*     * If we got a classid, then we need to try to lookup the class without     * doing any class loading. If we can't do this, then we cannot     * resolve the entry without class loading.     *     * If compilingCausesClassLoading is true, then there is no need to     * check if the class is already loaded.     *     * NOTE: This check for a loaded class isn't 100% accurate. It's possible     * that the class is loaded, but loading has not yet been initiated by     * the ClassLoader of currentCb.     */    if (classID != CVM_TYPEID_ERROR#ifdef CVM_JIT	&& !CVMglobals.jit.compilingCausesClassLoading#endif	)    {	CVMClassBlock* cb = NULL;	CVMClassLoaderICell* currLoader = CVMcbClassLoader(currentCb);	CVMBool isSystemClassLoader = CVM_FALSE;	/*	 * If the current class loader is the systemClassLoader, then that	 * allows us to do preloader lookups and do loadcache lookups	 * using the NULL class loader. This is because we know that the	 * systemClassLoader always defers to the NULL class loader first.	 * This helps us to resolve java.* and sun.* classes that are	 * loaded, but haven't been referenced by the application yet.	 */	if (currLoader != NULL) {	    CVMID_icellSameObject(ee, currLoader, CVMsystemClassLoader(ee),				  isSystemClassLoader);	}	/*	 * If the the class is primitive or the class	 * is a primitive array, then we can do a preloader lookup first.	 */	if (CVMtypeidIsPrimitive(classID) || 	    (CVMtypeidIsArray(classID) &&	     CVMtypeidIsPrimitive(CVMtypeidGetArrayBasetype(classID))))	{	    cb = CVMpreloaderLookupFromType(ee, classID, NULL);	} 	if (cb == NULL) {	    CVMBool needLoaderCacheUpdate = CVM_FALSE;	    CVM_LOADERCACHE_LOCK(ee);	    cb = CVMloaderCacheLookup(ee, classID, currLoader);	    if (cb == NULL && isSystemClassLoader) {		cb = CVMloaderCacheLookup(ee, classID, NULL);		needLoaderCacheUpdate = (cb != NULL);	    }	    CVM_LOADERCACHE_UNLOCK(ee);	    if (needLoaderCacheUpdate) {		/* Add to the loadercache so when CVMcpResolveEntryFromClass()		 * is called, we don't end up invoking currLoader.loadClass().		 */		if (!CVMloaderCacheAdd(ee, cb, currLoader)) {		    /* clear exception and fetched cb */		    CVMclearLocalException(ee);		    cb = NULL;		}	    }	}	if ((cb == NULL) || !CVMcbCheckRuntimeFlag(cb, LINKED)) {	    return CVM_FALSE; /* resolving would cause class loading */	}    }    /*     * If we get here it means that we can resolve this entry without     * causing class loading, so just do it. However, it is possible for     * an exception to occur due to access checks, so we need to check     * for this and treat the entry as unresolved in this case.     */    if (!CVMcpResolveEntryFromClass(ee, currentCb, cp, cpIndex)) {	CVMassert(CVMlocalExceptionOccurred(ee));	CVMclearLocalException(ee);	return CVM_FALSE;    } else {	return CVM_TRUE; /* entry is now resolved */    }}/* * CVMprivate_cpExtractTypeIDFromUnresolvedEntry - extracts the typeID * from a yet-unresolved constant pool entry. * * Also handles the case where another thread beats us to resolving * this constant pool entry. Returns CVM_TRUE if the c.p. entry ended * up being resolved, and CVM_FALSE if it remained unresolved.   */CVMBoolCVMprivate_cpExtractTypeIDFromUnresolvedEntry(CVMExecEnv* ee,					      CVMClassBlock* currentCb, 					      CVMConstantPool* cp, 					      CVMUint16 cpIndex,					      CVMTypeID* p_typeid){    CVMConstantPoolEntryType cpType;    /*     * We need to make sure the cp entry is not resolved and get its     * contents while holding the lock. Otherwise it could get resolved     * after we do the check, but before we grab the entry, in which     * case the data we get is not what we expect.     */    CVMcpLock(ee);    cpType = CVMcpEntryType(cp, cpIndex);    if (cpType != CVM_CONSTANT_ClassTypeID && p_typeid != NULL) {	*p_typeid = CVM_TYPEID_ERROR;    }    if (CVMcpIsResolved(cp, cpIndex)) {	/* it's already resolved by another thread. No need to assign           to p_typeid */	CVMcpUnlock(ee);	return CVM_TRUE;     }    /*      * Get the classID of the class the entry refers to. This is key to     * how this function works. If the class that is referred to is      * already loaded, then we can resolve this entry without causing     * any class loading.     */    if (cpType != CVM_CONSTANT_ClassTypeID) {	CVMUint16 typeIDIdx;	/* also set p_typeid so we can return it to the caller if needed */	typeIDIdx = CVMcpGetMemberRefTypeIDIdx(cp, cpIndex);	if (p_typeid != NULL) {	    if (cpType == CVM_CONSTANT_Fieldref) {		*p_typeid = CVMcpGetFieldTypeID(cp, typeIDIdx);	    } else {		*p_typeid = CVMcpGetMethodTypeID(cp, typeIDIdx);	    }	}    } else {        if (p_typeid != NULL) {	    *p_typeid = CVMcpGetClassTypeID(cp, cpIndex);        }    }        /* We are all done accessing the constant pool, so we can unlock now */    CVMcpUnlock(ee);	    return CVMcpIsResolved(cp, cpIndex); /* final chance to find resolved					    entry */}/* * CVMcpLookupClassAndVerifyAccess - Lookup the specified classID and * verify that the current class can access it. */static CVMClassBlock*CVMcpLookupClassAndVerifyAccess(CVMExecEnv* ee,				CVMClassBlock* currentCb,				CVMClassTypeID classID){    CVMClassBlock* resolvedCb = 	CVMclassLookupByTypeFromClass(ee, classID, CVM_FALSE, currentCb);    if (resolvedCb == NULL) {        /* Exception already thrown */        return NULL;    } else if (!CVMverifyClassAccess(ee, currentCb, resolvedCb, CVM_TRUE)){	CVMthrowIllegalAccessError(ee, 				   "try to access class %C from class %C",				   resolvedCb, currentCb);	return NULL;    } else {	return resolvedCb;    }}/*  * CVMprivate_cpResolveEntryFromClass - resolve a constant pool entry. *   currentCb: the "current class" for security and class loading purposes. *   cp:        the constant pool *   cpIndex:   index of entry in cp to resolve *  * This function should only be called via the public CVMcpResolveEntry * and CVMcpResolveEntryFromClass macros. */CVMBoolCVMprivate_cpResolveEntryFromClass(CVMExecEnv* ee,				   CVMClassBlock* currentCb, 				   CVMConstantPool* cp, 				   CVMUint16 cpIndex){    CVMConstantPoolEntryType cpType;    CVMFieldBlock*  resolvedFb = NULL;    CVMMethodBlock* resolvedMb = NULL;    /* The cp index, classID, and cb for any class we may resolve,      * including the class referred to by a FieldRef or MethodRef.     */    CVMUint16       classCpIndex;    CVMClassBlock*  resolvedCb;    CVMClassTypeID  classID = CVM_TYPEID_ERROR;    /*     * We need to make sure the cp entry is not resolved and get its     * contents while holding the lock. Otherwise it could get resolved     * after we do the check, but before we grab the entry, in which     * case the data we get is not what we expect.     */    CVMcpLock(ee);    if (CVMcpIsResolved(cp, cpIndex)) {	CVMcpUnlock(ee);	return CVM_TRUE;    }    cpType = CVMcpEntryType(cp, cpIndex);    switch(cpType) {    case CVM_CONSTANT_ClassTypeID: {	classID = CVMcpGetClassTypeID(cp, cpIndex);	CVMcpUnlock(ee);	classCpIndex = cpIndex;	resolvedCb = 	    CVMcpLookupClassAndVerifyAccess(ee, currentCb, classID);	if (resolvedCb == NULL) {	    /* Exception already thrown */	    return CVM_FALSE;	}		break;    }        case CVM_CONSTANT_Fieldref:    case CVM_CONSTANT_Methodref:     case CVM_CONSTANT_InterfaceMethodref: {	CVMClassLoaderICell* currentLoader = 	    (currentCb != NULL) ? CVMcbClassLoader(currentCb) : NULL;	CVMUint16 typeIDIdx = CVMcpGetMemberRefTypeIDIdx(cp, cpIndex);	classCpIndex  = CVMcpGetMemberRefClassIdx(cp, cpIndex);	/* First, resolve reference to the class */	if (!CVMcpIsResolved(cp, classCpIndex)) {	    classID = CVMcpGetClassTypeID(cp, classCpIndex);	    CVMcpUnlock(ee);		    resolvedCb = 		CVMcpLookupClassAndVerifyAccess(ee, currentCb, classID);	    if (resolvedCb == NULL) {		/* Exception already thrown */		return CVM_FALSE;	    }	} else {	    CVMcpUnlock(ee);	    resolvedCb = CVMcpGetCb(cp, classCpIndex);	}	if (!CVMcbCheckRuntimeFlag(resolvedCb, LINKED)) {	    if (!CVMclassLink(ee, resolvedCb, CVM_FALSE)) {		return CVM_FALSE;	    }	}	

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?