jni_impl.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 2,209 行 · 第 1/5 页
C
2,209 行
CVMObjectICell* result; CVMassert(CVMframeIsFreelist(currentFrame)); CVMassert(currentFrame->mb == NULL); /* If the resultArg is NULL, we are not responsible for handing the object reference to the previous stack frame. This is important for making the JVMTI work. See the Java 1.2 JNI spec additions. */ if (resultArg == NULL) { CVMpopGCRootFrame(currentEE, jniLocalsStack, currentFrame); /* It is not required that the previous frame be JNI, because we're not going to try to get a "local ref" for the result argument. */ return NULL; } else { result = CVMjniNonNullICellPtrFor(resultArg); CVMID_localrootBegin(currentEE); { CVMID_localrootDeclare(CVMObjectICell, temp); /* * Hold the result in a temporary, so it doesn't get lost * when the locals frame is popped */ CVMID_icellAssign(currentEE, temp, result); CVMpopGCRootFrame(currentEE, jniLocalsStack, currentFrame); if (!CVMframeIsJNI(currentFrame)) { CVMjniFatalError(env, "can't return reference to " "non-JNI frame"); } CVMassert(CVMframeIsJNI(currentFrame)); jniFrame = CVMgetJNIFrame(currentFrame); /* * Now get a new slot for the result */ CVMframeAlloc(currentEE, jniLocalsStack, jniFrame, returnVal); CVMID_icellAssign(currentEE, &returnVal->ref, temp); } CVMID_localrootEnd(); /* * Don't return ICells containing NULL. * * %comment: rt011 */ if (CVMID_icellIsNull(&returnVal->ref)) { return NULL; } else { return &returnVal->ref; } }}/* * Make global ref, and make it point to the same object 'value' points to */jobject JNICALLCVMjniNewGlobalRef(JNIEnv *env, jobject ref){#if 0 /* This might break JNI code, but it is good for debugging cvm code */#ifdef CVM_DEBUG_ASSERTS CVMassert(!CVMlocalExceptionOccurred(CVMjniEnv2ExecEnv(env)));#endif#endif if ((ref == NULL) || CVMID_icellIsNull(ref)) { /* * If ref is NULL, or ref points to a cell containing a NULL * (a cleared weak global ref), return NULL. */ return NULL; } else { CVMExecEnv* currentEE = CVMjniEnv2ExecEnv(env); CVMObjectICell* cell = CVMID_getGlobalRoot(currentEE); if (cell != NULL) { CVMID_icellAssign(currentEE, cell, ref);#ifdef CVM_JVMPI if (CVMjvmpiEventJNIGlobalrefAllocIsEnabled()) { CVMjvmpiPostJNIGlobalrefAllocEvent(currentEE, cell); }#endif /* CVM_JVMPI */ } else { CVMthrowOutOfMemoryError(currentEE, NULL); } return cell; }}/* * Delete global ref */void JNICALLCVMjniDeleteGlobalRef(JNIEnv *env, jobject ref){ /* Apparently Sheng's book, which contains the revised JNI spec, says that deleting a NULL global ref is a no-op */ /* %comment: rt012 */ if (ref != NULL) { CVMExecEnv* currentEE = CVMjniEnv2ExecEnv(env);#ifdef CVM_JVMPI if (CVMjvmpiEventJNIGlobalrefFreeIsEnabled()) { CVMjvmpiPostJNIGlobalrefFreeEvent(currentEE, ref); }#endif /* CVM_JVMPI */ CVMID_freeGlobalRoot(currentEE, ref); }}/* Purpose: Allocates a weak global ref. */static jweak JNICALLCVMjniNewWeakGlobalRef(JNIEnv* env, jobject ref){ if ((ref == NULL) || CVMID_icellIsNull(ref)) { /* * If ref is NULL, or ref points to a cell containing a NULL * (a cleared weak global ref), return NULL. */ return NULL; } else { CVMExecEnv* currentEE = CVMjniEnv2ExecEnv(env); CVMObjectICell* cell = CVMID_getWeakGlobalRoot(currentEE); if (cell != NULL) { CVMID_icellAssign(currentEE, cell, ref);#ifdef CVM_JVMPI if (CVMjvmpiEventJNIWeakGlobalrefAllocIsEnabled()) { CVMjvmpiPostJNIWeakGlobalrefAllocEvent(currentEE, cell); }#endif /* CVM_JVMPI */ } else { CVMthrowOutOfMemoryError(currentEE, NULL); } return cell; }}/* Purpose: Releases the specified weak global ref. */static void JNICALLCVMjniDeleteWeakGlobalRef(JNIEnv* env, jweak ref){ /* Apparently Sheng's book, which contains the revised JNI spec, says that deleting a NULL global ref is a no-op */ /* %comment: rt012 */ if (ref != NULL) { CVMExecEnv* currentEE = CVMjniEnv2ExecEnv(env);#ifdef CVM_JVMPI if (CVMjvmpiEventJNIWeakGlobalrefFreeIsEnabled()) { CVMjvmpiPostJNIWeakGlobalrefFreeEvent(currentEE, ref); }#endif /* CVM_JVMPI */ CVMID_freeWeakGlobalRoot(currentEE, ref); }}/* * CVMjniDefineClass - define a class. Used by Classloader.defineClass. */static jclass JNICALLCVMjniDefineClass(JNIEnv *env, const char *name, jobject loaderRef, const jbyte *buf, jsize bufLen){ CVMExecEnv* ee = CVMjniEnv2ExecEnv(env); CVMClassICell* classRoot; /* define the class */ classRoot = CVMdefineClass(ee, name, loaderRef, (CVMUint8*)buf, bufLen, NULL, CVM_FALSE); if (classRoot == NULL) { return NULL; } /* load superclasses in a non-recursive way */ (*env)->CallVoidMethod(env, classRoot, CVMglobals.java_lang_Class_loadSuperClasses); if (CVMexceptionOccurred(ee)) { CVMjniDeleteLocalRef(env, classRoot); return NULL; } return classRoot;}jclass JNICALLCVMjniFindClass(JNIEnv *env, const char *name){ CVMExecEnv* ee = CVMjniEnv2ExecEnv(env); CVMClassLoaderICell* loader; CVMClassBlock* callerCb = CVMgetCallerClass(ee, 0); /* * According to JNI spec, 'name' must be a fully-qualified class name, * which is a package name, delimited by "/", followed by the class * name. First check name and throw NoClassDefFoundError if it's not * legal, instead of throwing the exception after the class is actually * created. */ if (strchr(name, '.') != NULL) { CVMthrowNoClassDefFoundError(ee, "Bad class name %s", name); return NULL; }#ifdef CVM_CLASSLOADING CVMassert(!CVMlocalExceptionOccurred(ee)); if (callerCb != NULL) { /* Special handling to make sure JNI_OnLoad and JNI_OnUnload are * executed in the correct class context. */ if (callerCb == CVMsystemClass(java_lang_ClassLoader_NativeLibrary)) { jobject clazz; CVMMethodBlock* mb = CVMglobals.java_lang_ClassLoader_NativeLibrary_getFromClass; clazz = (*env)->CallStaticObjectMethod(env, CVMcbJavaInstance(callerCb), mb); if (CVMexceptionOccurred(ee)) { return NULL; } callerCb = CVMgcSafeClassRef2ClassBlock(ee, clazz); } loader = CVMcbClassLoader(callerCb); } else { loader = CVMclassGetSystemClassLoader(ee); if (loader == NULL) { return NULL; /* exception already thrown */ } }#else loader = NULL;#endif /* CVM_CLASSLOADING */ CVMassert(!CVMlocalExceptionOccurred(ee)); { CVMObjectICell* pd = callerCb ? CVMcbProtectionDomain(callerCb) : NULL; CVMClassBlock* cb = CVMclassLookupByNameFromClassLoader(ee, name, CVM_TRUE, loader, pd, CVM_TRUE); if (cb != NULL) { return CVMjniNewLocalRef(env, CVMcbJavaInstance(cb)); } return NULL; }}/* * Native Bootstrap */jint JNICALLCVMjniRegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, jint nMethods){ CVMExecEnv* ee = CVMjniEnv2ExecEnv(env); CVMClassBlock *cb = CVMgcSafeClassRef2ClassBlock(ee, clazz); CVMBool inROM = CVMcbIsInROM(cb); int i; for (i = 0; i < nMethods; ++i) { struct CVMMethodBlock *mb; char *name = methods[i].name; char *sig = methods[i].signature; mb = CVMclassGetDeclaredMethodBlock(ee, cb, name, sig); if (mb == NULL || !CVMmbIs(mb, NATIVE)) { CVMthrowNoSuchMethodError(ee, "%s", name); return JNI_EINVAL; } } /* %comment: rt013 */ for (i = 0; i < nMethods; ++i) { struct CVMMethodBlock *mb; const char *name = methods[i].name; const char *sig = methods[i].signature; void *nativeProc = methods[i].fnPtr; int invoker; mb = CVMclassGetDeclaredMethodBlock(ee, cb, name, sig); CVMassert(mb != NULL && CVMmbIs(mb, NATIVE));#ifdef JDK12 if (verbose_jni) { jio_fprintf(stderr, "[Registering JNI native method %s.%s]\n", cbName(mb->fb.clazz), mb->fb.name); }#endif invoker = CVMmbIs(mb, SYNCHRONIZED) ? CVM_INVOKE_JNI_SYNC_METHOD : CVM_INVOKE_JNI_METHOD; if (inROM) { CVMassert(CVMmbInvokerIdx(mb) == invoker); CVMassert(CVMmbNativeCode(mb) == nativeProc);#ifdef CVM_JIT CVMassert(CVMmbJitInvoker(mb) == (void*)CVMCCMinvokeJNIMethod);#endif } else {#ifdef CVM_JVMTI if (CVMjvmtiShouldPostNativeMethodBind()) { CVMUint8* new_nativeCode = NULL; CVMjvmtiPostNativeMethodBind(ee, mb, (CVMUint8*)nativeProc, &new_nativeCode); if (new_nativeCode != NULL) { nativeProc = (void *)new_nativeCode; } }#endif CVMmbSetInvokerIdx(mb, invoker); CVMmbNativeCode(mb) = (CVMUint8 *)nativeProc;#ifdef CVM_JIT CVMmbJitInvoker(mb) = (void*)CVMCCMinvokeJNIMethod;#endif } } return JNI_OK;}jint JNICALLCVMjniUnregisterNatives(JNIEnv *env, jclass clazz){#ifdef CVM_CLASSLOADING CVMExecEnv* ee = CVMjniEnv2ExecEnv(env); CVMClassBlock *cb = CVMgcSafeClassRef2ClassBlock(ee, clazz); CVMBool inROM = CVMcbIsInROM(cb); int i; if (inROM) { return JNI_OK; } /* %comment: rt013 */ for (i = 0; i < CVMcbMethodCount(cb); ++i) { CVMMethodBlock* mb = CVMcbMethodSlot(cb, i); if (CVMmbIs(mb, NATIVE)) { CVMmbSetInvokerIdx(mb, CVM_INVOKE_LAZY_JNI_METHOD); CVMmbNativeCode(mb) = NULL;#ifdef CVM_JIT CVMmbJitInvoker(mb) = (void*)CVMCCMletInterpreterDoInvoke;#endif } } return JNI_OK;#else return JNI_ERR;#endif}static jmethodIDCVMjniGetXMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig, jboolean isStatic){ CVMExecEnv * ee; CVMClassBlock* cb; CVMMethodTypeID tid; CVMMethodBlock* mb; ee = CVMjniEnv2ExecEnv(env); cb = CVMjniGcSafeRef2Class(ee, clazz); if (!CVMclassInit(ee, cb)) { return NULL; } /* * We need to use the "new" function, because the "lookup" function * is only valid when we know that the type already exists. */ tid = CVMtypeidNewMethodIDFromNameAndSig(ee, name, sig); if (tid != CVM_TYPEID_ERROR) { /* never search superclasses for constructors */ mb = CVMclassGetMethodBlock(cb, tid, isStatic); CVMtypeidDisposeMethodID(ee, tid); } else { mb = NULL; CVMclearLocalException(ee); } if (mb == NULL) { CVMthrowNoSuchMethodError(ee, "%s", name); return NULL; } return mb;}jmethodID JNICALLCVMjniGetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig){ return CVMjniGetXMethodID(env, clazz, name, sig, JNI_TRUE);}jmethodID JNICALLCVMjniGetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig){ return CVMjniGetXMethodID(env, clazz, name, sig, JNI_FALSE);}static jfieldIDCVMjniGetXFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig, jboolean isStatic){ CVMExecEnv * ee; CVMClassBlock* cb; CVMFieldTypeID tid; CVMFieldBlock* fb; ee = CVMjniEnv2ExecEnv(env); cb = CVMjniGcSafeRef2Class(ee, clazz); if (!CVMclassInit(ee, cb)) { return NULL; } /* * We need to use the "new" function, because the "lookup" function * is only valid when we know that the type already exists. */ tid = CVMtypeidNewFieldIDFromNameAndSig(ee, name, sig); if (tid != CVM_TYPEID_ERROR) { fb = CVMclassGetFieldBlock(cb, tid, isStatic); CVMtypeidDisposeFieldID(ee, tid); } else { fb = NULL; CVMclearLocalException(ee); } if (fb == NULL || (CVMfbIs(fb, STATIC) != isStatic)) { CVMthrowNoSuchFieldError(ee, "%s", name); return NULL ; } return fb;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?