jni_impl.c

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

C
2,209
字号
/* * @(#)jni_impl.c	1.380 06/10/31 * * 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.  * */#define _JNI_IMPLEMENTATION_#include "javavm/include/defs.h"#include "javavm/include/objects.h"#include "javavm/include/classes.h"#include "javavm/include/interpreter.h"#include "javavm/include/stacks.h"#include "javavm/include/localroots.h"#include "javavm/include/globalroots.h"#include "javavm/include/indirectmem.h"#include "javavm/include/typeid.h"#include "javavm/include/jni_impl.h"#include "javavm/include/gc_common.h"#include "javavm/include/preloader.h"#include "javavm/include/basictypes.h"#include "javavm/include/common_exceptions.h"#include "javavm/include/utils.h"#include "javavm/include/timestamp.h"#include "javavm/include/stackwalk.h"#include "javavm/include/packages.h"#ifndef CDC_10#include "javavm/include/javaAssertions.h"#endif#include "generated/offsets/java_lang_Class.h"#include "generated/offsets/java_lang_String.h"#include "generated/offsets/java_lang_Thread.h"#include "generated/jni/java_lang_Thread.h"#include "generated/cni/sun_misc_CVM.h"#include "javavm/include/porting/time.h"#include "javavm/include/porting/threads.h"#include "javavm/include/porting/system.h"#include "javavm/include/porting/globals.h"#include "javavm/include/porting/ansi/stdarg.h"#include "javavm/export/jni.h"#ifdef CVM_XRUN#include "javavm/include/xrun.h"#endif#ifdef CVM_AGENTLIB#include "javavm/include/agentlib.h"#endif#ifdef CVM_CLASSLOADING#include "javavm/include/porting/java_props.h"#include "native/java/util/zip/zip_util.h"#include "javavm/include/porting/io.h"#include "javavm/include/porting/path.h"#endif#ifdef CVM_REFLECT#include "javavm/include/reflect.h"#endif#ifdef CVM_JVMTI#include "javavm/export/jvmti.h"#endif#ifdef CVM_JVMPI#include "javavm/include/jvmpi_impl.h"#endif#ifdef CVM_JIT#include "javavm/include/ccm_runtime.h"#include "javavm/include/porting/jit/ccm.h"#include "javavm/include/jit_common.h"#include "javavm/include/jit/jitstats.h"#include "javavm/include/jit/jitcodebuffer.h"#endif#ifdef CVM_DEBUG_ASSERTS#include "javavm/include/constantpool.h"#endif#ifdef CVM_EMBEDDED_HOOK#include "javavm/include/hook.h"#endif#ifdef CVM_HW#include "include/hw.h"#endif#undef MIN#define MIN(x,y) ((x) < (y) ? (x) : (y))/* * If gc latency is of concern, you may want to reduce this buffer size. * It will affect the maximum amount of time spent gc-unsafe while copying * characters from the heap to a local buffer. */#undef  MAX_CHARS_PER_ACCESS#define MAX_CHARS_PER_ACCESS	100/* %comment c006 */#define CVMjniNonNullICellPtrFor(jobj) \    CVMID_NonNullICellPtrFor(jobj)static CVMUint32CVMjniAvailableCapacity(CVMStack* stack, CVMJNIFrame* frame){    if (!CVMaddressInStackChunk(frame, stack->currentStackChunk)) {        CVMStackChunk* chunk = stack->currentStackChunk;        CVMUint32 available = 0;               while (!CVMaddressInStackChunk(frame, chunk)) {            available += (CVMUint32)(chunk->end_data - chunk->data);            chunk = chunk->prev;        }        CVMassert(CVMaddressInStackChunk(frame, chunk));        available += (((CVMUint32)chunk->end_data -                      (CVMUint32)frame) / sizeof(CVMStackVal32)) -                    CVMJNIFrameCapacity - frame->inUse;        return available;    } else {	/* 	 * casting to the result type jint should be done after 	 * subtracting the addresses frame->topOfStack and frame	 * because jint can not hold a native pointer on 64 bit platforms	 */	return (jint)((((CVMAddr)((stack->currentStackChunk)->end_data) -                     (CVMAddr)frame) / sizeof(CVMStackVal32)) -                    CVMJNIFrameCapacity - frame->inUse);    }}/* private types */typedef charJNI_PushArguments_t(JNIEnv *env, CVMterseSigIterator  *terse_signature,                    CVMFrame *current_frame, const void *args);/* Forward declarations */static JNI_PushArguments_t CVMjniPushArgumentsVararg;static JNI_PushArguments_t CVMjniPushArgumentsArray;static void CVMjniInvoke(JNIEnv *env, jobject obj, jmethodID methodID,    JNI_PushArguments_t pushArguments, const void *args,    CVMUint16 info, jvalue *retValue);/* Definitions */void JNICALLCVMjniFatalError(JNIEnv *env, const char *msg){    CVMconsolePrintf("JNI FATAL ERROR: %s\n", msg);#if defined(CVM_DEBUG) && defined(CVM_DEBUG_DUMPSTACK)    CVMdumpStack(&CVMjniEnv2ExecEnv(env)->interpreterStack,		 CVM_FALSE, CVM_FALSE, 100);#endif     CVMexit(1);}#undef CVMjniGcUnsafeRef2Class#define CVMjniGcUnsafeRef2Class(ee, cl) CVMgcUnsafeClassRef2ClassBlock(ee, cl)#undef CVMjniGcSafeRef2Class#define CVMjniGcSafeRef2Class(ee, cl) CVMgcSafeClassRef2ClassBlock(ee, cl)/*  * CreateLocalRef is used to create a local ref in the current frame of * the specified thread.  It should check the free list first. */CVMObjectICell*CVMjniCreateLocalRef0(CVMExecEnv *ee, CVMExecEnv *targetEE){    CVMStack*      jniLocalsStack = &targetEE->interpreterStack;    CVMFrame*	   currentFrame   = jniLocalsStack->currentFrame;    CVMStackVal32* result         = NULL;    CVMassert(CVMframeIsJNI(currentFrame));    CVMframeAlloc(ee, jniLocalsStack, CVMgetJNIFrame(currentFrame), result);    if (result != NULL) {	return &result->ref;    } else {	/* The JNI spec says that if an attempt to allocate a localRef	 * fails, it's a fatal error since the caller really should have	 * called EnsureLocalCapacity() first. 	 */	CVMjniFatalError(CVMexecEnv2JniEnv(ee), 			 "Out of memory when expanding local ref "			 "table beyond capacity");	return NULL;    }}/*  * CreateLocalRef is used to create a local ref in the current frame * of the current thread. */CVMObjectICell*CVMjniCreateLocalRef(CVMExecEnv *ee){    return CVMjniCreateLocalRef0(ee, ee);}/* Version information */jint JNICALLCVMjniGetVersion(JNIEnv *env){    return JNI_VERSION_1_4;}/*  * NewLocalRef is used to create a local ref in the specified frame. It * should check the free list first. */jobject JNICALLCVMjniNewLocalRef(JNIEnv *env, jobject obj){    CVMExecEnv*     currentEE      = CVMjniEnv2ExecEnv(env);    CVMObjectICell* resultCell     = NULL;    CVMassert(CVMframeIsJNI(CVMeeGetCurrentFrame(currentEE)));    if ((obj == NULL) || CVMID_icellIsNull(obj)) {	/*	 * If ref is NULL, or ref points to a cell containing a NULL	 * (a cleared weak global ref), return NULL.	 */	return NULL;    } else {	resultCell = CVMjniCreateLocalRef(currentEE);	if (resultCell == NULL) {	    return NULL;	}	CVMID_icellAssign(currentEE, resultCell, obj);	return resultCell;    }}/* * Is a given ref in any of the chunks of 'frame'? */static CVMBoolCVMjniRefInFrame(CVMStackChunk* chunk, CVMFrame* frame, CVMStackVal32* ref){    CVMJNIFrame*   jniFrame = CVMgetJNIFrame(frame);    CVMStackVal32* tos      = frame->topOfStack;    /*     * Traverse chunks from the last chunk of the frame to the first     */    while (!CVMaddressInStackChunk(frame, chunk)) {	if ((ref < tos) && (ref >= chunk->data)) {	    return CVM_TRUE;	}	chunk = chunk->prev;	tos = chunk->end_data;    }    /* Now we are looking at the first chunk of the frame.       Do a range check. */    if ((ref < tos) && (ref >= jniFrame->vals)) {	return CVM_TRUE;    } else {	return CVM_FALSE;    }}/*  * DeleteLocalRef is used delete a JNI local ref in the specified frame. */void JNICALLCVMjniDeleteLocalRef(JNIEnv *env, jobject obj){    CVMExecEnv*    currentEE      = CVMjniEnv2ExecEnv(env);    CVMStack*      jniLocalsStack = &currentEE->interpreterStack;    CVMStackVal32* refToFree	  = (CVMStackVal32*)obj;    CVMFrame*      frame;    CVMFrame*      calleeFrame;    CVMStackChunk* chunk;    CVMStackWalkContext swc;    frame = jniLocalsStack->currentFrame;    CVMassert(frame != NULL);    CVMassert(CVMframeIsJNI(frame));    if (refToFree == NULL) {	return; /* Nothing to do */    }    /*      * Walk the stack through all local roots and JNI frames. These     * may be PushLocalFrame frames, or the frame of a JNI     * method. If the local frame belongs to any one of these frames     * (each of which may span multiple stack chunks), return it to     * the right free list.       */    CVMstackwalkInit(jniLocalsStack, &swc);    frame = swc.frame;    chunk = swc.chunk;    do {	if (CVMjniRefInFrame(chunk, frame, refToFree)) {	    CVMframeFree(CVMgetJNIFrame(frame), refToFree);	    return;	}	calleeFrame = frame;	CVMstackwalkPrev(&swc);	frame = swc.frame;	chunk = swc.chunk;	CVMassert(frame != NULL);    } while (CVMframeIsJNI(frame));    /*     * Well, we couldn't find where this ref belongs. Maybe it is an argument     * to this JNI function.     *     * At this point:     *    frame-        the caller of the JNI method     *    calleeFrame-  the frame of the JNI method     */    if (CVMframeIsInterpreter(frame)) {	/* We are now at the caller of the JNI method. Its top of stack is set	   to just above the arguments to the JNI method. See if refToFree	   was one of these arguments. */	CVMStackVal32* topOfArgs = frame->topOfStack;	if ((refToFree <  topOfArgs) &&	    (refToFree >= topOfArgs - CVMmbArgsSize(calleeFrame->mb))) {	    CVMID_icellSetNull(obj);	    return;	}    }    /*     * If we got here, this cannot be a valid ref. Just ignore -- we can't     * do anything useful with this.     */    CVMdebugPrintf(("Attempt to delete invalid local ref -- ignoring!\n"));}/* * Ensure local refs capacity in frame (in number of words). */jint JNICALLCVMjniEnsureLocalCapacity(JNIEnv *env, jint capacity){    CVMExecEnv*    ee             = CVMjniEnv2ExecEnv(env);    CVMStack*      jniLocalsStack = &ee->interpreterStack;    CVMFrame*	   currentFrame   = jniLocalsStack->currentFrame;    CVMJNIFrame*   jniFrame;    CVMUint32      available;    CVMassert(CVMframeIsJNI(currentFrame));    jniFrame = CVMgetJNIFrame(currentFrame);    available = CVMjniAvailableCapacity(jniLocalsStack, jniFrame);    /* The 'capacity <= 0' is necessary if capacity is negative */    if (capacity <= 0 || capacity <= available) {	return JNI_OK; /* We have enough to satisfy the capacity request */    }    /* Now expand the stack */    capacity -= available;     CVMD_gcUnsafeExec(ee, {	CVMexpandStack(ee, jniLocalsStack, capacity, CVM_TRUE, CVM_TRUE);    });        if (CVMlocalExceptionOccurred(ee)) {	/* The JNI spec says to throw an OutOfMemoryError. However,	 * CVMexpandStack may have thrown a StackOverflowError	 * error instead.	 */	CVMclearLocalException(ee);	CVMthrowOutOfMemoryError(ee, NULL);	return JNI_ENOMEM;    } else {	return JNI_OK;    }}/* * Push local frame that can accommodate 'capacity' local refs */jint JNICALLCVMjniPushLocalFrame(JNIEnv *env, jint capacity){    CVMExecEnv*    ee             = CVMjniEnv2ExecEnv(env);    CVMStack*      jniLocalsStack = &ee->interpreterStack;    CVMFrame*      currentFrame   = jniLocalsStack->currentFrame;    /* Make sure we have the room on the stack for the specified bytes. */    if (!CVMensureCapacity(ee, jniLocalsStack, 			   capacity + CVMJNIFrameCapacity)) {	/* The JNI spec says to throw an OutOfMemoryError. However,	 * CVMensureCapacity may have thrown a StackOverflowError	 * error instead.	 */	CVMclearLocalException(ee);	CVMthrowOutOfMemoryError(ee, NULL);	return JNI_ENOMEM;    }    /* We know this will succeed, since we've ensured larger capacity above */    CVMpushGCRootFrame(ee, jniLocalsStack, currentFrame,		       CVMJNIFrameCapacity, CVM_FRAMETYPE_JNI);    CVMjniFrameInit(CVMgetJNIFrame(currentFrame), CVM_TRUE);    /* Ready to go! */    return JNI_OK;}/* * Pop local frame, and return a ref to the old frame */jobject JNICALLCVMjniPopLocalFrame(JNIEnv *env, jobject resultArg){    CVMExecEnv*    currentEE      = CVMjniEnv2ExecEnv(env);    CVMStack*      jniLocalsStack = &currentEE->interpreterStack;    CVMFrame*      currentFrame   = jniLocalsStack->currentFrame;    CVMJNIFrame*   jniFrame;    CVMStackVal32* returnVal;

⌨️ 快捷键说明

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