/* * @(#) $(JCGO)/include/jcgojniv.c -- * a part of the JCGO runtime subsystem. ** * Project: JCGO (http://www.ivmaisoft.com/jcgo/) * Copyright (C) 2001-2012 Ivan Maidanski * All rights reserved. */ /** * This file is compiled together with the files produced by the JCGO * translator (do not include and/or compile this file directly). */ /* * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. ** * This software 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 (GPL) for more details. ** * Linking this library statically or dynamically with other modules is * making a combined work based on this library. Thus, the terms and * conditions of the GNU General Public License cover the whole * combination. ** * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ #ifdef JCGO_VER #ifndef JCGO_JNILOCKEDOBJS_DEFLEN #define JCGO_JNILOCKEDOBJS_DEFLEN 28 #endif #define JCGO_ACCMOD_INTERFACE 0x200 #define JCGO_ACCMOD_ABSTRACT 0x400 #ifdef JCGO_SEHTRY #ifdef OBJT_java_lang_VMThrowable #ifdef JCGO_NOCREATJVM #define JCGO_NATCBACK_BEGIN(pJniEnv) { jObject jcgo_throwable; jObjectArr jcgo_localObjs; (void)jcgo_jniCallbackEnter(pJniEnv, &jcgo_throwable, &jcgo_localObjs); { JCGO_TRY_BLOCK { #else #define JCGO_NATCBACK_BEGIN(pJniEnv) { jObject jcgo_throwable; jObjectArr jcgo_localObjs; if (jcgo_jniCallbackEnter(pJniEnv, &jcgo_throwable, &jcgo_localObjs) || !setjmp(JCGO_JNI_GETTCB(pJniEnv)->jbuf)) { JCGO_TRY_BLOCK { #endif #else #define JCGO_NATCBACK_BEGIN(pJniEnv) { jObject jcgo_throwable; jObjectArr jcgo_localObjs; (void)jcgo_jniCallbackEnter(pJniEnv, &jcgo_throwable, &jcgo_localObjs); { JCGO_TRY_BLOCK { #endif #define JCGO_NATCBACK_END(pJniEnv) } JCGO_TRY_LEAVE { if (JCGO_JNI_GETTCB(pJniEnv)->throwable != jnull) { jcgo_throwable = JCGO_JNI_GETTCB(pJniEnv)->throwable; JCGO_JNI_GETTCB(pJniEnv)->throwable = jnull; goto jcgo_trynatcaught; } } JCGO_TRY_SEHNOP; jcgo_trynatcaught:; } jcgo_jniCallbackLeave(pJniEnv, jcgo_throwable, jcgo_localObjs); } #else #define JCGO_NATCBACK_BEGIN(pJniEnv) { struct jcgo_try_s jcgo_try; jObjectArr jcgo_localObjs; jcgo_jniCallbackEnter(pJniEnv, &jcgo_try, &jcgo_localObjs); if (!setjmp(jcgo_try.jbuf)) { #define JCGO_NATCBACK_END(pJniEnv) } jcgo_jniCallbackLeave(pJniEnv, jcgo_localObjs); } #endif STATICDATA CONST struct JNINativeInterface_ jcgo_jniNatIface; STATIC jint JNICALL jcgo_JniEnsureLocalCapacity( JNIEnv *pJniEnv, jint capacity ); JCGO_NOSEP_INLINE void CFASTCALL jcgo_abortOnJniEnvCorrupted( void ) { JCGO_FATAL_ABORT("JNIEnv corrupted!"); } JCGO_NOSEP_INLINE void CFASTCALL jcgo_abortOnNonThrowable( void ) { JCGO_FATAL_ABORT("Cannot throw non-throwable object!"); } #ifndef OBJT_java_lang_VMClass JCGO_NOSEP_INLINE void CFASTCALL jcgo_abortOnVMClassNotFound( void ) { JCGO_FATAL_ABORT("Cannot find java.lang.VMClass!"); } #endif /* ! OBJT_java_lang_VMClass */ #ifdef JCGO_NOGC JCGO_NOSEP_INLINE #else #ifdef JCGO_THREADS JCGO_NOSEP_STATIC #else JCGO_NOSEP_INLINE #endif #endif jObject CFASTCALL jcgo_jniDeRef( jobject obj ) { if (obj != NULL) { #ifndef JCGO_NOGC #ifdef JCGO_THREADS #ifndef JCGO_FNLZDATA_OMITREFQUE if (JCGO_EXPECT_FALSE(*(void **)((volatile char *)obj - (int)sizeof(void *)) == JCGO_PTR_RESERVED)) return *(jObject volatile *)obj != jnull ? (jObject)JCGO_MEM_CALLWITHSYNC(&jcgo_refGetPtr, obj) : jnull; #endif #endif #endif return *(jObject *)obj; } return jnull; } STATIC jobject CFASTCALL jcgo_jniToLocalRef( JNIEnv *pJniEnv, jObject obj ) { jObjectArr localObjs; jObjectArr prevLocalObjs; jObject *pobj; jint len; if (obj != jnull) for (;;) { localObjs = JCGO_JNI_GETTCB(pJniEnv)->localObjs; while (localObjs != jnull) { len = JCGO_ARRAY_NZLENGTH(localObjs); while (--len > 0) if (JCGO_ARR_INTERNALACC(jObject, localObjs, len) == jnull) { *(pobj = &JCGO_ARR_INTERNALACC(jObject, localObjs, len)) = obj; return (jobject)pobj; } prevLocalObjs = (jObjectArr)JCGO_ARR_INTERNALACC(jObject, localObjs, 1); if ((jObjectArr)JCGO_ARR_INTERNALACC(jObject, localObjs, 0) != prevLocalObjs) break; localObjs = prevLocalObjs; } if (jcgo_JniEnsureLocalCapacity(pJniEnv, 1)) JCGO_FATAL_ABORT("Too many JNI local references!"); } return NULL; } #ifdef JCGO_SEHTRY STATIC int CFASTCALL jcgo_jniCallbackEnter( JNIEnv *pJniEnv, jObject *pthrowable, jObjectArr *plocalObjs ) { struct jcgo_tcb_s *tcb; if (pJniEnv == NULL) jcgo_abortOnJniEnvCorrupted(); if ((tcb = JCGO_JNI_GETTCB(pJniEnv))->jniEnv != &jcgo_jniNatIface || (tcb->insideCallback++, jcgo_restoreTCB(tcb) < 0)) jcgo_abortOnJniEnvCorrupted(); *pthrowable = tcb->nativeExc; tcb->nativeExc = jnull; *plocalObjs = tcb->localObjs; tcb->localObjs = jnull; tcb->insideCallback--; tcb->jniEnv = NULL; #ifdef JCGO_NOCREATJVM return 0; #else return (int)tcb->insideJniCall; #endif } JCGO_NOSEP_INLINE void CFASTCALL jcgo_jniCallbackLeave( JNIEnv *pJniEnv, jObject throwable, jObjectArr localObjs ) { struct jcgo_tcb_s *tcb; (tcb = JCGO_JNI_GETTCB(pJniEnv))->jniEnv = &jcgo_jniNatIface; tcb->localObjs = localObjs; #ifdef JCGO_THREADS jcgo_saveTCB(); #endif tcb->nativeExc = throwable; } #else /* JCGO_SEHTRY */ STATIC void CFASTCALL jcgo_jniCallbackEnter( JNIEnv *pJniEnv, struct jcgo_try_s *pCurTry, jObjectArr *plocalObjs ) { struct jcgo_tcb_s *tcb; if (JCGO_EXPECT_FALSE(pJniEnv == NULL)) jcgo_abortOnJniEnvCorrupted(); if ((tcb = JCGO_JNI_GETTCB(pJniEnv))->jniEnv != &jcgo_jniNatIface || (tcb->insideCallback++, jcgo_restoreTCB(tcb) < 0)) jcgo_abortOnJniEnvCorrupted(); pCurTry->throwable = tcb->nativeExc; pCurTry->last = tcb->pCurTry; tcb->pCurTry = pCurTry; #ifdef JCGO_THREADS pCurTry->pCurMon = tcb->pCurMon; tcb->pCurMon = NULL; #endif tcb->nativeExc = jnull; *plocalObjs = tcb->localObjs; tcb->localObjs = jnull; tcb->insideCallback--; tcb->jniEnv = NULL; } STATIC void CFASTCALL jcgo_jniCallbackLeave( JNIEnv *pJniEnv, jObjectArr localObjs ) { struct jcgo_tcb_s *tcb = JCGO_JNI_GETTCB(pJniEnv); struct jcgo_try_s *pCurTry = tcb->pCurTry; #ifdef JCGO_THREADS tcb->pCurMon = pCurTry->pCurMon; #endif tcb->pCurTry = pCurTry->last; tcb->jniEnv = &jcgo_jniNatIface; tcb->localObjs = localObjs; #ifdef JCGO_THREADS jcgo_saveTCB(); #endif tcb->nativeExc = pCurTry->throwable; } #endif /* ! JCGO_SEHTRY */ STATIC void CFASTCALL jcgo_jniThrowNullPointerException( JNIEnv *pJniEnv ) { #ifdef OBJT_java_lang_VMThrowable JCGO_NATCBACK_BEGIN(pJniEnv) JCGO_THROW_EXC(java_lang_VMThrowable__createNullPointerException0X__()); JCGO_NATCBACK_END(pJniEnv) #endif } JCGO_NOSEP_INLINE void CFASTCALL jcgo_jniHandleInstanceOfNullClass( JNIEnv *pJniEnv ) { jObject nativeExc; if ((nativeExc = JCGO_JNI_GETTCB(pJniEnv)->nativeExc) != jnull) { #ifdef OBJT_java_lang_NoClassDefFoundError if (jcgo_instanceOf0(OBJT_java_lang_NoClassDefFoundError, MAXT_java_lang_NoClassDefFoundError, nativeExc)) JCGO_JNI_GETTCB(pJniEnv)->nativeExc = jnull; #endif } else jcgo_jniThrowNullPointerException(pJniEnv); } STATIC jint JNICALL jcgo_JniGetVersion( JNIEnv *pJniEnv ) { return (jint)JNI_VERSION_1_6; } STATIC jclass JNICALL jcgo_JniDefineClass( JNIEnv *pJniEnv, CONST char *name, jobject loader, CONST jbyte *buf, jsize bufLen ) { #ifdef OBJT_java_lang_VMClassLoader_ClassParser java_lang_Class JCGO_TRY_VOLATILE aclass; jbyteArr buffer; if (JCGO_EXPECT_FALSE(JCGO_JNI_GETTCB(pJniEnv)->nativeExc != jnull)) return NULL; if (JCGO_EXPECT_FALSE(buf == NULL)) { jcgo_jniThrowNullPointerException(pJniEnv); return NULL; } aclass = jnull; JCGO_NATCBACK_BEGIN(pJniEnv) buffer = (jbyteArr)jcgo_newArray(JCGO_CORECLASS_FOR(OBJT_jbyte), 0, (jint)bufLen); JCGO_MEM_HCOPY(&JCGO_ARR_INTERNALACC(jbyte, buffer, 0), (void *)buf, (JCGO_ALLOCSIZE_T)bufLen); aclass = java_lang_VMClassLoader_ClassParser__defineClass0X__LsLoBA( JCGO_EXPECT_TRUE(name != NULL) ? jcgo_utfMakeString(name) : jnull, (java_lang_Object)jcgo_jniDeRef(loader), buffer); JCGO_NATCBACK_END(pJniEnv) return (jclass)jcgo_jniToLocalRef(pJniEnv, (jObject)aclass); #else if (*(void *volatile *)&jcgo_noTypesClassArr.jcgo_methods != NULL) JCGO_FATAL_ABORT("Cannot find java.lang.VMClassLoader$ClassParser!"); return NULL; #endif } STATIC jclass JNICALL jcgo_JniFindClass( JNIEnv *pJniEnv, CONST char *name ) { java_lang_Class baseClass; java_lang_Class JCGO_TRY_VOLATILE aclass; java_lang_String str; jcharArr arr; unsigned len; unsigned dims; int i; int j; unsigned char ch; if (JCGO_EXPECT_FALSE(JCGO_JNI_GETTCB(pJniEnv)->nativeExc != jnull)) return NULL; if (JCGO_EXPECT_FALSE(name == NULL)) { jcgo_jniThrowNullPointerException(pJniEnv); return NULL; } dims = 0; while (*(name + dims) == (char)0x5b) /*'['*/ dims++; aclass = jnull; JCGO_NATCBACK_BEGIN(pJniEnv) len = dims; while (*(name + len)) len++; baseClass = jnull; if (dims && (int)(len - dims) == 1) switch ((int)(*(name + dims))) { case 0x5a: /*'Z'*/ baseClass = JCGO_CORECLASS_FOR(OBJT_jboolean); break; case 0x42: /*'B'*/ baseClass = JCGO_CORECLASS_FOR(OBJT_jbyte); break; case 0x43: /*'C'*/ baseClass = JCGO_CORECLASS_FOR(OBJT_jchar); break; case 0x53: /*'S'*/ baseClass = JCGO_CORECLASS_FOR(OBJT_jshort); break; case 0x49: /*'I'*/ baseClass = JCGO_CORECLASS_FOR(OBJT_jint); break; case 0x4a: /*'J'*/ baseClass = JCGO_CORECLASS_FOR(OBJT_jlong); break; case 0x46: /*'F'*/ baseClass = JCGO_CORECLASS_FOR(OBJT_jfloat); break; case 0x44: /*'D'*/ baseClass = JCGO_CORECLASS_FOR(OBJT_jdouble); break; default: break; } str = jnull; if ((!dims || *(name + len - 1) == (char)0x3b) && /*';'*/ len <= (((unsigned)-1) >> 1) - (unsigned)16) { i = (int)dims; if (*(name + dims) == (char)0x4c && /*'L'*/ *(name + len - 1) == (char)0x3b) /*';'*/ { i++; len--; } if (JCGO_EXPECT_TRUE(i < (int)len)) { arr = (jcharArr)jcgo_newArray(JCGO_CORECLASS_FOR(OBJT_jchar), 0, (int)len - i); str = (java_lang_String)jcgo_newObject((jvtable)&java_lang_String_methods); JCGO_FIELD_NZACCESS(str, value) = (void *)arr; JCGO_FIELD_NZACCESS(str, count) = (int)len - i; j = 0; do { ch = (unsigned char)(*(name + i)); if (JCGO_EXPECT_FALSE(ch == (unsigned char)0x2e || /*'.'*/ ch > (unsigned char)0x7f)) { str = jnull; break; } JCGO_ARR_INTERNALACC(jchar, arr, j) = (jchar)(ch != (unsigned char)0x2f ? /*'/'*/ ch : (unsigned char)0x2e); /*'.'*/ j++; } while (++i < (int)len); } } if (JCGO_EXPECT_TRUE(str != jnull)) baseClass = jcgo_findClass(str, 0); if (JCGO_EXPECT_TRUE(baseClass != jnull)) { if (dims) { #ifdef OBJT_java_lang_VMClass aclass = java_lang_VMClass__arrayClassOf0X__LcI(baseClass, (jint)dims); #else jcgo_abortOnVMClassNotFound(); #endif } else { aclass = baseClass; } } #ifdef OBJT_java_lang_VMThrowable else JCGO_THROW_EXC( java_lang_VMThrowable__createNoClassDefFoundError0X__LsI(str, 0)); #endif JCGO_NATCBACK_END(pJniEnv) return (jclass)jcgo_jniToLocalRef(pJniEnv, (jObject)aclass); } STATIC jclass JNICALL jcgo_JniGetSuperclass( JNIEnv *pJniEnv, jclass clazz ) { java_lang_Class aclass; if (JCGO_EXPECT_FALSE(JCGO_JNI_GETTCB(pJniEnv)->nativeExc != jnull)) return NULL; aclass = (java_lang_Class)jcgo_jniDeRef((jobject)clazz); if (JCGO_EXPECT_FALSE(aclass == jnull)) { jcgo_jniThrowNullPointerException(pJniEnv); return NULL; } return (jclass)jcgo_jniToLocalRef(pJniEnv, (unsigned)((jvtable)&JCGO_METHODS_OF(JCGO_FIELD_NZACCESS(aclass, vmdata)))->jcgo_typeid - (unsigned)(OBJT_jarray + 1) >= (unsigned)(OBJT_void + JCGO_DIMS_MAX - 1) ? (jObject)JCGO_FIELD_NZACCESS(aclass, superclass) : (jObject)JCGO_CLASSREF_OF(java_lang_Object__class)); } STATIC jboolean JNICALL jcgo_JniIsAssignableFrom( JNIEnv *pJniEnv, jclass subclass, jclass clazz ) { java_lang_Class srcClass = (java_lang_Class)jcgo_jniDeRef((jobject)subclass); java_lang_Class aclass; if (srcClass == jnull || (aclass = (java_lang_Class)jcgo_jniDeRef((jobject)clazz)) == jnull) { jcgo_jniHandleInstanceOfNullClass(pJniEnv); return (jboolean)JNI_FALSE; } return (jboolean)(jcgo_isAssignable(srcClass, aclass, 0, 0) ? JNI_TRUE : JNI_FALSE); } STATIC jint JNICALL jcgo_JniThrow( JNIEnv *pJniEnv, jthrowable obj ) { #ifdef OBJT_java_lang_Throwable jObject jobj; struct jcgo_tcb_s *tcb = JCGO_JNI_GETTCB(pJniEnv); if (JCGO_EXPECT_FALSE(tcb->nativeExc != jnull)) return (jint)JNI_ERR; jobj = jcgo_jniDeRef((jobject)obj); if (JCGO_EXPECT_FALSE(jobj == jnull)) { jcgo_jniThrowNullPointerException(pJniEnv); return (jint)JNI_ERR; } if (!jcgo_instanceOf0(OBJT_java_lang_Throwable, MAXT_java_lang_Throwable, jobj)) jcgo_abortOnNonThrowable(); #ifdef JCGO_THREADS if (JCGO_EXPECT_FALSE(tcb->stopExc != jnull)) return (jint)JNI_ERR; #endif tcb->nativeExc = jobj; #else jcgo_abortOnNonThrowable(); #endif return 0; } STATIC jint JNICALL jcgo_JniThrowNew( JNIEnv *pJniEnv, jclass clazz, CONST char *msg ) { #ifdef OBJT_java_lang_Throwable java_lang_Class aclass; java_lang_String str; java_lang_String name; jObject jobj; struct jcgo_jobjectarr_s jcgo_stackobj1; CONST struct jcgo_reflect_s *jcgo_reflect; CONST struct jcgo_methodentry_s *pentry; jObject (CFASTCALL *rtn)(jObject) = 0; jObjectArr methodsTypes; jObjectArr methodsName; jObjectArr methodsDims; jObjectArr argTypes; jbyteArr paramDims; jObjectArr objectArgs; int slotNoArg; int slotStrArg; int i; int count; JCGO_TRY_VOLATILE int res; if (JCGO_EXPECT_FALSE(JCGO_JNI_GETTCB(pJniEnv)->nativeExc != jnull)) return (jint)JNI_ERR; aclass = (java_lang_Class)jcgo_jniDeRef((jobject)clazz); if (JCGO_EXPECT_FALSE(aclass == jnull)) { jcgo_jniThrowNullPointerException(pJniEnv); return (jint)JNI_ERR; } #ifdef JCGO_THREADS if (JCGO_EXPECT_FALSE(JCGO_JNI_GETTCB(pJniEnv)->stopExc != jnull)) return (jint)JNI_ERR; #endif res = (int)JNI_ERR; JCGO_NATCBACK_BEGIN(pJniEnv) str = msg != NULL ? jcgo_utfMakeString(msg) : jnull; jobj = jnull; pentry = NULL; slotNoArg = -1; slotStrArg = -1; if (JCGO_EXPECT_TRUE((JCGO_FIELD_NZACCESS(aclass, modifiers) & (JCGO_ACCMOD_INTERFACE | JCGO_ACCMOD_ABSTRACT)) == 0)) { jcgo_reflect = ((jvtable)&JCGO_METHODS_OF( JCGO_FIELD_NZACCESS(aclass, vmdata)))->jcgo_reflect; if (JCGO_EXPECT_TRUE(jcgo_reflect != NULL) && (methodsTypes = jcgo_reflect->methodsTypes) != jnull) { count = (int)JCGO_ARRAY_NZLENGTH(methodsTypes); methodsName = jcgo_reflect->methodsName; methodsDims = jcgo_reflect->methodsDims; pentry = jcgo_reflect->methodsEntry; for (i = 0; i < count; i++) if (methodsName == jnull || (name = (java_lang_String) JCGO_ARR_INTERNALACC(jObject, methodsName, i)) == jnull || !JCGO_FIELD_NZACCESS(name, count)) { argTypes = (jObjectArr)JCGO_ARR_INTERNALACC(jObject, methodsTypes, i); if (argTypes != jnull && JCGO_ARRAY_NZLENGTH(argTypes)) { if (str != jnull && JCGO_ARRAY_NZLENGTH(argTypes) == 1 && (java_lang_Class)JCGO_ARR_INTERNALACC(jObject, argTypes, 0) == JCGO_CLASSREF_OF(java_lang_String__class) && (methodsDims == jnull || (paramDims = (jbyteArr)JCGO_ARR_INTERNALACC(jObject, methodsDims, i)) == jnull || !JCGO_ARR_INTERNALACC(jbyte, paramDims, 0))) { slotStrArg = i; break; } } else { slotNoArg = i; if (str == jnull) break; } } } else if ((rtn = ((jvtable)&JCGO_METHODS_OF( JCGO_FIELD_NZACCESS(aclass, vmdata)))->jcgo_thisRtn) != 0) slotNoArg = 0; if (JCGO_EXPECT_TRUE((slotNoArg & slotStrArg) >= 0)) jobj = jcgo_newObject( (jvtable)&JCGO_METHODS_OF(JCGO_FIELD_NZACCESS(aclass, vmdata))); } if (!jcgo_instanceOf0(OBJT_java_lang_Throwable, MAXT_java_lang_Throwable, jobj)) jcgo_abortOnNonThrowable(); #ifdef JCGO_STDCLINIT jcgo_clinitTrig(aclass); #else #ifdef JCGO_CLINITCHK jcgo_clinitCheckOrder(aclass); #endif #endif if (pentry != NULL) { objectArgs = jnull; if (slotStrArg >= 0) { objectArgs = JCGO_STACKOBJ_OBJARRNEW(jcgo_stackobj1, jObjectArr_methods, JCGO_CLASSREF_OF(java_lang_Object__class), 1); JCGO_ARR_INTERNALACC(jObject, objectArgs, 0) = (jObject)str; pentry = pentry + (unsigned)slotStrArg; } else pentry = pentry + (unsigned)slotNoArg; jobj = (*pentry->mproxy)(pentry->jmethod, jobj, jnull, jnull, jnull, jnull, objectArgs); } else jobj = (*rtn)(jobj); res = 0; if (JCGO_EXPECT_FALSE(*(void *volatile *) &jcgo_noTypesClassArr.jcgo_methods != NULL)) JCGO_THROW_EXC(jobj); JCGO_NATCBACK_END(pJniEnv) return (jint)res; #else jcgo_abortOnNonThrowable(); return 0; #endif } STATIC jthrowable JNICALL jcgo_JniExceptionOccurred( JNIEnv *pJniEnv ) { jObject ex = JCGO_JNI_GETTCB(pJniEnv)->nativeExc; #ifdef JCGO_THREADS if (JCGO_EXPECT_TRUE(ex == jnull)) ex = JCGO_JNI_GETTCB(pJniEnv)->stopExc; #endif return (jthrowable)jcgo_jniToLocalRef(pJniEnv, ex); } STATIC void JNICALL jcgo_JniExceptionDescribe( JNIEnv *pJniEnv ) { #ifdef OBJT_java_lang_VMThread JCGO_TRY_VOLATILE int res = 0; jObject ex; if ((ex = JCGO_JNI_GETTCB(pJniEnv)->nativeExc) == jnull) return; JCGO_NATCBACK_BEGIN(pJniEnv) res = (int)java_lang_VMThread__jniExceptionDescribe0X__Lo( (java_lang_Object)ex); JCGO_NATCBACK_END(pJniEnv) if (JCGO_EXPECT_TRUE(res != 0)) return; JCGO_JNI_GETTCB(pJniEnv)->nativeExc = ex; #else #ifndef JCGO_NOFATALMSG if (JCGO_JNI_GETTCB(pJniEnv)->nativeExc == jnull) return; #endif #endif #ifndef JCGO_NOFATALMSG JCGO_JNI_FUNC(jcgo_JavaWriteLnToStderr)(" JNI exception occurred!", ""); #endif } STATIC void JNICALL jcgo_JniExceptionClear( JNIEnv *pJniEnv ) { JCGO_JNI_GETTCB(pJniEnv)->nativeExc = jnull; } STATIC void JNICALL jcgo_JniFatalError( JNIEnv *pJniEnv, CONST char *msg ) { JCGO_FATAL_ABORT(msg != NULL && *msg ? msg : "JNI error!"); } STATIC jint JNICALL jcgo_JniPushLocalFrame( JNIEnv *pJniEnv, jint capacity ) { jObjectArr JCGO_TRY_VOLATILE localObjs = jnull; JCGO_NATCBACK_BEGIN(pJniEnv) localObjs = (jObjectArr)jcgo_newArray( JCGO_CLASSREF_OF(java_lang_Object__class), 0, (capacity > 0 ? capacity : 1) + 3); JCGO_NATCBACK_END(pJniEnv) if (JCGO_EXPECT_FALSE(localObjs == jnull)) return (jint)JNI_ERR; JCGO_ARR_INTERNALACC(jObject, localObjs, 0) = (jObject)JCGO_JNI_GETTCB(pJniEnv)->localObjs; JCGO_JNI_GETTCB(pJniEnv)->localObjs = (jObjectArr)localObjs; return 0; } STATIC jobject JNICALL jcgo_JniPopLocalFrame( JNIEnv *pJniEnv, jobject obj ) { jint len; jObject jobj = jcgo_jniDeRef(obj); jObjectArr localObjs = JCGO_JNI_GETTCB(pJniEnv)->localObjs; jObjectArr prevLocalObjs; do { if (localObjs == jnull || (JCGO_JNI_GETTCB(pJniEnv)->localObjs = (jObjectArr)JCGO_ARR_INTERNALACC(jObject, localObjs, 0)) == jnull) JCGO_FATAL_ABORT("Cannot delete JNI first local frame!"); len = JCGO_ARRAY_NZLENGTH(localObjs); prevLocalObjs = (jObjectArr)JCGO_ARR_INTERNALACC(jObject, localObjs, 1); while (--len > 0) JCGO_ARR_INTERNALACC(jObject, localObjs, len) = jnull; } while ((localObjs = JCGO_JNI_GETTCB(pJniEnv)->localObjs) == prevLocalObjs); return jcgo_jniToLocalRef(pJniEnv, jobj); } STATIC jobject JNICALL jcgo_JniNewGlobalRef( JNIEnv *pJniEnv, jobject obj ) { jObjectArr nextEntry; jObjectArr prevEntry; jObjectArr JCGO_TRY_VOLATILE queEntry; jObject jobj; if (JCGO_EXPECT_FALSE(JCGO_JNI_GETTCB(pJniEnv)->nativeExc != jnull)) return NULL; jobj = jcgo_jniDeRef(obj); if (JCGO_EXPECT_FALSE(jobj == jnull)) return NULL; queEntry = jnull; JCGO_NATCBACK_BEGIN(pJniEnv) prevEntry = (jObjectArr)jcgo_newArray( JCGO_CLASSREF_OF(java_lang_Object__class), 0, 3); JCGO_ARR_INTERNALACC(jObject, prevEntry, 2) = jobj; JCGO_CRITMOD_BEGIN(jcgo_jniGlobalRefsMutex) nextEntry = jcgo_globData.jniGlobalRefsQue; if (JCGO_EXPECT_TRUE(nextEntry != jnull)) { JCGO_ARR_INTERNALACC(jObject, prevEntry, 0) = (jObject)nextEntry; JCGO_ARR_INTERNALACC(jObject, nextEntry, 1) = (jObject)prevEntry; } jcgo_globData.jniGlobalRefsQue = prevEntry; JCGO_CRITMOD_END(jcgo_jniGlobalRefsMutex) queEntry = prevEntry; JCGO_NATCBACK_END(pJniEnv) return JCGO_EXPECT_TRUE(queEntry != jnull) ? (jobject)&JCGO_ARR_INTERNALACC(jObject, queEntry, 2) : NULL; } STATIC void JNICALL jcgo_JniDeleteGlobalRef( JNIEnv *pJniEnv, jobject globalref ) { jObjectArr queEntry; jObjectArr nextEntry; jObjectArr prevEntry; if (JCGO_EXPECT_TRUE(globalref != NULL)) { queEntry = (jObjectArr)((volatile char *)globalref - (JCGO_OFFSET_OF(struct jcgo_jobjectarr_s, jObject) + sizeof(jObject) * 2)); if (JCGO_ARRAY_NZLENGTH(queEntry) != 3 || JCGO_METHODS_OF(queEntry)->jcgo_typeid != OBJT_jarray + OBJT_void || JCGO_ARR_INTERNALACC(jObject, queEntry, 2) == jnull) JCGO_FATAL_ABORT("Invalid JNI global reference!"); #ifndef JCGO_PARALLEL JCGO_NATCBACK_BEGIN(pJniEnv) #endif JCGO_ARR_INTERNALACC(jObject, queEntry, 2) = jnull; JCGO_CRITMOD_BEGIN(jcgo_jniGlobalRefsMutex) nextEntry = (jObjectArr)JCGO_ARR_INTERNALACC(jObject, queEntry, 0); prevEntry = (jObjectArr)JCGO_ARR_INTERNALACC(jObject, queEntry, 1); if (JCGO_EXPECT_TRUE(nextEntry != jnull)) JCGO_ARR_INTERNALACC(jObject, nextEntry, 1) = (jObject)prevEntry; if (JCGO_EXPECT_TRUE(prevEntry != jnull)) JCGO_ARR_INTERNALACC(jObject, prevEntry, 0) = (jObject)nextEntry; else jcgo_globData.jniGlobalRefsQue = nextEntry; JCGO_CRITMOD_END(jcgo_jniGlobalRefsMutex) #ifndef JCGO_PARALLEL JCGO_NATCBACK_END(pJniEnv) #endif } } STATIC void JNICALL jcgo_JniDeleteLocalRef( JNIEnv *pJniEnv, jobject localref ) { if (JCGO_EXPECT_TRUE(localref != NULL)) *(jObject *)localref = jnull; } STATIC jboolean JNICALL jcgo_JniIsSameObject( JNIEnv *pJniEnv, jobject obj1, jobject obj2 ) { return (jboolean)(jcgo_jniDeRef(obj1) == jcgo_jniDeRef(obj2) ? JNI_TRUE : JNI_FALSE); } STATIC jobject JNICALL jcgo_JniNewLocalRef( JNIEnv *pJniEnv, jobject obj ) { return jcgo_jniToLocalRef(pJniEnv, jcgo_jniDeRef(obj)); } STATIC jint JNICALL jcgo_JniEnsureLocalCapacity( JNIEnv *pJniEnv, jint capacity ) { jint len = 0; jObjectArr localObjs; jObjectArr JCGO_TRY_VOLATILE newLocalObjs; localObjs = JCGO_JNI_GETTCB(pJniEnv)->localObjs; if (JCGO_EXPECT_TRUE(capacity > 0)) { if (JCGO_EXPECT_TRUE(localObjs != jnull) && (len = JCGO_ARRAY_NZLENGTH(localObjs)) > capacity) { while (--len > 0) if (JCGO_ARR_INTERNALACC(jObject, localObjs, len) == jnull && --capacity <= 0) return 0; len = JCGO_ARRAY_NZLENGTH(localObjs); } if (JCGO_EXPECT_FALSE(localObjs == jnull || (len += capacity) <= 0)) len = (jint)(((u_jint)-1) >> 1); newLocalObjs = jnull; JCGO_NATCBACK_BEGIN(pJniEnv) newLocalObjs = (jObjectArr)jcgo_newArray( JCGO_CLASSREF_OF(java_lang_Object__class), 0, len); JCGO_NATCBACK_END(pJniEnv) if (JCGO_EXPECT_FALSE(newLocalObjs == jnull)) return (jint)JNI_ERR; JCGO_ARR_INTERNALACC(jObject, newLocalObjs, 0) = (jObject)localObjs; JCGO_ARR_INTERNALACC(jObject, newLocalObjs, 1) = (jObject)localObjs; JCGO_JNI_GETTCB(pJniEnv)->localObjs = (jObjectArr)newLocalObjs; } return 0; } STATIC jobject JNICALL jcgo_JniAllocObject( JNIEnv *pJniEnv, jclass clazz ) { java_lang_Class aclass; jObject JCGO_TRY_VOLATILE jobj; if (JCGO_EXPECT_FALSE(JCGO_JNI_GETTCB(pJniEnv)->nativeExc != jnull)) return NULL; aclass = (java_lang_Class)jcgo_jniDeRef((jobject)clazz); if (JCGO_EXPECT_FALSE(aclass == jnull)) { jcgo_jniThrowNullPointerException(pJniEnv); return NULL; } jobj = jnull; JCGO_NATCBACK_BEGIN(pJniEnv) if (JCGO_EXPECT_TRUE((JCGO_FIELD_NZACCESS(aclass, modifiers) & (JCGO_ACCMOD_INTERFACE | JCGO_ACCMOD_ABSTRACT)) == 0)) jobj = jcgo_newObject( (jvtable)&JCGO_METHODS_OF(JCGO_FIELD_NZACCESS(aclass, vmdata))); #ifdef OBJT_java_lang_VMThrowable else JCGO_THROW_EXC( java_lang_VMThrowable__createInstantiationException0X__Lc(aclass)); #endif JCGO_NATCBACK_END(pJniEnv) return jcgo_jniToLocalRef(pJniEnv, (jObject)jobj); } STATIC jclass JNICALL jcgo_JniGetObjectClass( JNIEnv *pJniEnv, jobject obj ) { jObject jobj; java_lang_Class JCGO_TRY_VOLATILE aclass; int dims; if (JCGO_EXPECT_FALSE(JCGO_JNI_GETTCB(pJniEnv)->nativeExc != jnull)) return NULL; jobj = jcgo_jniDeRef(obj); if (JCGO_EXPECT_FALSE(jobj == jnull)) { jcgo_jniThrowNullPointerException(pJniEnv); return NULL; } dims = JCGO_METHODS_OF(jobj)->jcgo_typeid - (OBJT_jarray + OBJT_void); if ((unsigned)dims < (unsigned)JCGO_DIMS_MAX) { aclass = jnull; #ifdef OBJT_java_lang_VMClass JCGO_NATCBACK_BEGIN(pJniEnv) aclass = java_lang_VMClass__arrayClassOf0X__LcI( JCGO_OBJARR_COMPCLASS((jObjectArr)jobj), (jint)(dims + 1)); JCGO_NATCBACK_END(pJniEnv) #else jcgo_abortOnVMClassNotFound(); #endif } else aclass = JCGO_METHODS_OF(jobj)->jcgo_class; return (jclass)jcgo_jniToLocalRef(pJniEnv, (jObject)aclass); } STATIC jboolean JNICALL jcgo_JniIsInstanceOf( JNIEnv *pJniEnv, jobject obj, jclass clazz ) { jObject jobj; java_lang_Class aclass = (java_lang_Class)jcgo_jniDeRef((jobject)clazz); java_lang_Class srcClass; int typenum; if (JCGO_EXPECT_FALSE(aclass == jnull)) { jcgo_jniHandleInstanceOfNullClass(pJniEnv); return (jboolean)JNI_FALSE; } jobj = jcgo_jniDeRef(obj); if (jobj == jnull) return (jboolean)JNI_FALSE; typenum = JCGO_METHODS_OF(jobj)->jcgo_typeid; srcClass = JCGO_METHODS_OF(jobj)->jcgo_class; if (typenum >= OBJT_jarray + OBJT_void && typenum < OBJT_jarray + OBJT_void + JCGO_DIMS_MAX) srcClass = JCGO_OBJARR_COMPCLASS((jObjectArr)jobj); else typenum = OBJT_jarray + OBJT_void - 1; return (jboolean)(jcgo_isAssignable(srcClass, aclass, typenum - (OBJT_jarray + OBJT_void - 1), 0) ? JNI_TRUE : JNI_FALSE); } STATIC jint JNICALL jcgo_JniRegisterNatives( JNIEnv *pJniEnv, jclass clazz, CONST JNINativeMethod *methods, jint nMethods ) { /* dummy */ return 0; } STATIC jint JNICALL jcgo_JniUnregisterNatives( JNIEnv *pJniEnv, jclass clazz ) { /* dummy */ return 0; } STATIC jint JNICALL jcgo_JniMonitorEnter( JNIEnv *pJniEnv, jobject obj ) { jObject jobj = jcgo_jniDeRef(obj); #ifdef JCGO_THREADS JCGO_TRY_VOLATILE int res; struct jcgo_tcb_s *tcb; jObjectArr listEntry; jObjectArr *pentry; jint len; #endif if (JCGO_EXPECT_FALSE(jobj == jnull)) { if (JCGO_JNI_GETTCB(pJniEnv)->nativeExc == jnull) jcgo_jniThrowNullPointerException(pJniEnv); return (jint)JNI_ERR; } #ifdef JCGO_THREADS res = (int)JNI_ERR; JCGO_NATCBACK_BEGIN(pJniEnv) JCGO_GET_CURTCB(&tcb); if (jcgo_monEnterInner(jobj, tcb)) { pentry = &tcb->jniLockedObjs; for (;;) { listEntry = *pentry; if (JCGO_EXPECT_FALSE(listEntry == jnull)) { { JCGO_TRY_BLOCK { *pentry = (jObjectArr)jcgo_newArray( JCGO_CLASSREF_OF(java_lang_Object__class), 0, JCGO_JNILOCKEDOBJS_DEFLEN); } JCGO_TRY_LEAVE { if (JCGO_EXPECT_FALSE(*pentry == jnull)) jcgo_monLeaveInner(jobj, tcb); } JCGO_TRY_FINALLYEND } JCGO_ARR_INTERNALACC(jObject, *pentry, JCGO_JNILOCKEDOBJS_DEFLEN - 1) = jobj; break; } len = JCGO_ARRAY_NZLENGTH(listEntry); while (--len > 0) if (JCGO_ARR_INTERNALACC(jObject, listEntry, len) == jnull) break; if (JCGO_EXPECT_TRUE(len != 0)) { JCGO_ARR_INTERNALACC(jObject, listEntry, len) = jobj; break; } pentry = (jObjectArr *)&JCGO_ARR_INTERNALACC(jObject, listEntry, 0); } } else { listEntry = (jObjectArr)jcgo_newArray( JCGO_CLASSREF_OF(java_lang_Object__class), 0, 2); JCGO_ARR_INTERNALACC(jObject, listEntry, 0) = jobj; JCGO_ARR_INTERNALACC(jObject, listEntry, 1) = (jObject)tcb->overlockedObjsList; tcb->overlockedObjsList = listEntry; } res = 0; JCGO_NATCBACK_END(pJniEnv) return (jint)res; #else return 0; #endif } STATIC jint JNICALL jcgo_JniMonitorExit( JNIEnv *pJniEnv, jobject obj ) { jObject jobj = jcgo_jniDeRef(obj); #ifdef JCGO_THREADS JCGO_TRY_VOLATILE int res; struct jcgo_tcb_s *tcb; jObjectArr listEntry; jObjectArr *pentry; jint len; #endif if (JCGO_EXPECT_FALSE(jobj == jnull)) { if (JCGO_JNI_GETTCB(pJniEnv)->nativeExc == jnull) jcgo_jniThrowNullPointerException(pJniEnv); return (jint)JNI_ERR; } #ifdef JCGO_THREADS res = (int)JNI_ERR; JCGO_NATCBACK_BEGIN(pJniEnv) JCGO_GET_CURTCB(&tcb); pentry = &tcb->overlockedObjsList; for (;;) { if ((listEntry = *pentry) == jnull) { #ifdef OBJT_java_lang_VMThread if (jcgo_monLeaveInner(jobj, tcb) < 0) java_lang_VMThread__throwIllegalMonitorStateException0X__(); #else jcgo_monLeaveInner(jobj, tcb); #endif for (listEntry = tcb->jniLockedObjs; listEntry != jnull; listEntry = (jObjectArr)JCGO_ARR_INTERNALACC(jObject, listEntry, 0)) { len = JCGO_ARRAY_NZLENGTH(listEntry); while (--len > 0) if (JCGO_EXPECT_FALSE(JCGO_ARR_INTERNALACC(jObject, listEntry, len) == jobj)) break; if (JCGO_EXPECT_TRUE(len != 0)) { JCGO_ARR_INTERNALACC(jObject, listEntry, len) = jnull; break; } } break; } if (JCGO_EXPECT_FALSE(JCGO_ARR_INTERNALACC(jObject, listEntry, 0) == jobj)) { *pentry = (jObjectArr)JCGO_ARR_INTERNALACC(jObject, listEntry, 1); break; } pentry = (jObjectArr *)&JCGO_ARR_INTERNALACC(jObject, listEntry, 1); } res = 0; JCGO_NATCBACK_END(pJniEnv) return (jint)res; #else return 0; #endif } STATIC jweak JNICALL jcgo_JniNewWeakGlobalRef( JNIEnv *pJniEnv, jobject obj ) { jObject jobj; #ifndef JCGO_FNLZDATA_OMITREFQUE jObjectArr listEntry; struct jcgo_refexthidden_s *pexthidden; #endif jweak JCGO_TRY_VOLATILE weakref; if (JCGO_EXPECT_FALSE(JCGO_JNI_GETTCB(pJniEnv)->nativeExc != jnull)) return NULL; jobj = jcgo_jniDeRef(obj); weakref = NULL; if (JCGO_EXPECT_TRUE(jobj != jnull)) { JCGO_NATCBACK_BEGIN(pJniEnv) #ifdef JCGO_FNLZDATA_OMITREFQUE #ifdef OBJT_java_lang_VMThrowable java_lang_VMThrowable__throwOutOfMemoryError0X__(); #endif #else listEntry = (jObjectArr)jcgo_newArray( JCGO_CLASSREF_OF(java_lang_Object__class), 0, 2); pexthidden = jcgo_newWeakQueRef(jnull, (jObject)listEntry, jobj, 1); if (JCGO_EXPECT_TRUE(pexthidden != NULL)) { #ifdef JCGO_THREADS *(void **)((volatile char *)&pexthidden->hidden.obj - (int)sizeof(void *)) = JCGO_PTR_RESERVED; #endif JCGO_ARR_INTERNALACC(jObject, listEntry, 0) = (jObject)pexthidden; JCGO_CRITMOD_BEGIN(jcgo_jniWeakRefsMutex) JCGO_ARR_INTERNALACC(jObject, listEntry, 1) = (jObject)jcgo_globData.jniWeakRefsList; jcgo_globData.jniWeakRefsList = listEntry; JCGO_CRITMOD_END(jcgo_jniWeakRefsMutex) weakref = (jweak)&pexthidden->hidden.obj; } #ifdef OBJT_java_lang_VMThrowable else java_lang_VMThrowable__throwOutOfMemoryError0X__(); #endif #endif JCGO_NATCBACK_END(pJniEnv) } return (jweak)weakref; } STATIC void JNICALL jcgo_JniDeleteWeakGlobalRef( JNIEnv *pJniEnv, jweak weakref ) { #ifndef JCGO_FNLZDATA_OMITREFQUE jObjectArr listEntry; jObjectArr prevEntry; struct jcgo_refexthidden_s *pexthidden; if (JCGO_EXPECT_TRUE(weakref != NULL)) { #ifndef JCGO_PARALLEL JCGO_NATCBACK_BEGIN(pJniEnv) #endif prevEntry = jnull; pexthidden = NULL; JCGO_CRITMOD_BEGIN(jcgo_jniWeakRefsMutex) listEntry = jcgo_globData.jniWeakRefsList; while (listEntry != jnull) { pexthidden = (struct jcgo_refexthidden_s *)JCGO_ARR_INTERNALACC(jObject, listEntry, 0); if (JCGO_EXPECT_TRUE(pexthidden != NULL) && JCGO_EXPECT_FALSE((jweak)(&pexthidden->hidden.obj) == weakref)) break; prevEntry = listEntry; listEntry = (jObjectArr)JCGO_ARR_INTERNALACC(jObject, listEntry, 1); } if (JCGO_EXPECT_TRUE(listEntry != jnull)) { if (JCGO_EXPECT_TRUE(prevEntry != jnull)) JCGO_ARR_INTERNALACC(jObject, prevEntry, 1) = JCGO_ARR_INTERNALACC(jObject, listEntry, 1); else jcgo_globData.jniWeakRefsList = (jObjectArr)JCGO_ARR_INTERNALACC(jObject, listEntry, 1); } JCGO_CRITMOD_END(jcgo_jniWeakRefsMutex) if (JCGO_EXPECT_TRUE(listEntry != jnull)) pexthidden->hidden.obj = jnull; else JCGO_FATAL_ABORT("Invalid JNI weak global reference!"); #ifndef JCGO_PARALLEL JCGO_NATCBACK_END(pJniEnv) #endif } #endif } STATIC jobjectRefType JNICALL jcgo_JniGetObjectRefType( JNIEnv *pJniEnv, jobject obj ) { jObjectArr localObjs; jObjectArr listEntry; #ifndef JCGO_FNLZDATA_OMITREFQUE struct jcgo_refexthidden_s *pexthidden; #endif ptrdiff_t index; #ifdef JCGO_PARALLEL jobjectRefType reftype; #else jobjectRefType JCGO_TRY_VOLATILE reftype; #endif reftype = JNIInvalidRefType; if (JCGO_EXPECT_TRUE(obj != NULL)) { localObjs = JCGO_JNI_GETTCB(pJniEnv)->localObjs; while (localObjs != jnull) { index = (jObject *)obj - &JCGO_ARR_INTERNALACC(jObject, localObjs, 0); if (index >= 2 && JCGO_ARRAY_NZLENGTH(localObjs) > index && JCGO_EXPECT_TRUE((unsigned)( (char *)obj - (char *)&JCGO_ARR_INTERNALACC(jObject, localObjs, 0)) % sizeof(jObject) == 0)) return JNILocalRefType; listEntry = (jObjectArr)JCGO_ARR_INTERNALACC(jObject, localObjs, 0); if ((jobject)&JCGO_ARR_INTERNALACC(jObject, localObjs, 1) == obj) return JCGO_EXPECT_TRUE((jObjectArr)JCGO_ARR_INTERNALACC(jObject, localObjs, 1) != listEntry) ? JNILocalRefType : JNIInvalidRefType; localObjs = listEntry; } #ifndef JCGO_PARALLEL JCGO_NATCBACK_BEGIN(pJniEnv) #endif #ifndef JCGO_FNLZDATA_OMITREFQUE JCGO_CRITMOD_BEGIN(jcgo_jniWeakRefsMutex) listEntry = jcgo_globData.jniWeakRefsList; while (listEntry != jnull) { pexthidden = (struct jcgo_refexthidden_s *)JCGO_ARR_INTERNALACC(jObject, listEntry, 0); if (JCGO_EXPECT_TRUE(pexthidden != NULL) && JCGO_EXPECT_FALSE((jobject)(&pexthidden->hidden.obj) == obj)) break; listEntry = (jObjectArr)JCGO_ARR_INTERNALACC(jObject, listEntry, 1); } JCGO_CRITMOD_END(jcgo_jniWeakRefsMutex) if (JCGO_EXPECT_FALSE(listEntry != jnull)) reftype = JNIWeakGlobalRefType; else #endif { JCGO_CRITMOD_BEGIN(jcgo_jniGlobalRefsMutex) listEntry = jcgo_globData.jniGlobalRefsQue; while (listEntry != jnull) { if (JCGO_EXPECT_FALSE((jobject)&JCGO_ARR_INTERNALACC(jObject, listEntry, 2) == obj)) break; listEntry = (jObjectArr)JCGO_ARR_INTERNALACC(jObject, listEntry, 0); } JCGO_CRITMOD_END(jcgo_jniGlobalRefsMutex) if (JCGO_EXPECT_TRUE(listEntry != jnull)) reftype = JNIGlobalRefType; } #ifndef JCGO_PARALLEL JCGO_NATCBACK_END(pJniEnv) #endif } return reftype; } STATIC jboolean JNICALL jcgo_JniExceptionCheck( JNIEnv *pJniEnv ) { #ifdef JCGO_THREADS if (JCGO_JNI_GETTCB(pJniEnv)->stopExc != jnull) return (jboolean)JNI_TRUE; #endif return (jboolean)(JCGO_JNI_GETTCB(pJniEnv)->nativeExc != jnull ? JNI_TRUE : JNI_FALSE); } #endif