** NativePointerHolder subclass represented by
** zClassName */;
volatile jmethodID midCtor /* klazz's no-arg constructor. Used by
- ** new_NativePointerHolder_object(). */;
+ ** new_NativePointerHolder_object(). */;
volatile jfieldID fidValue /* NativePointerHolder.nativePointer or
** OutputPointer.T.value */;
volatile jfieldID fidAggCtx /* sqlite3_context::aggregateContext. Used only
jobject jObj /* global ref to Java instance */;
jmethodID midCallback /* callback method. Signature depends on
** jObj's type */;
- jclass klazz /* global ref to jObj's class. Only needed
- ** by hooks which have an xDestroy() method.
- ** We can probably eliminate this and simply
- ** do the class lookup at the same
- ** (deferred) time we do the xDestroy()
- ** lookup. */;
};
/*
volatile jobject jFtsExt /* Global ref to Java singleton for the
Fts5ExtensionApi instance. */;
struct {
- volatile jclass klazz /* Global ref to the Fts5Phrase iter class */;
jfieldID fidA /* Fts5Phrase::a member */;
jfieldID fidB /* Fts5Phrase::b member */;
} jPhraseIter;
char * zMsg;
jclass const klazz = (*env)->GetObjectClass(env, jx);
mid = (*env)->GetMethodID(env, klazz, "toString", "()Ljava/lang/String;");
+ UNREF_L(klazz);
IFTHREW{
EXCEPTION_REPORT;
EXCEPTION_CLEAR;
}
/*
-** Extracts the (void xDestroy()) method from the given jclass and
-** applies it to jobj. If jObj is NULL, this is a no-op. If klazz is
-** NULL then it's derived from jobj. The lack of an xDestroy() method
-** is silently ignored and any exceptions thrown by xDestroy() trigger
-** a warning to stdout or stderr and then the exception is suppressed.
+** Extracts the (void xDestroy()) method from jObj and applies it to
+** jObj. If jObj is NULL, this is a no-op. The lack of an xDestroy()
+** method is silently ignored and any exceptions thrown by xDestroy()
+** trigger a warning to stdout or stderr and then the exception is
+** suppressed.
*/
-static void s3jni_call_xDestroy(JNIEnv * const env, jobject jObj, jclass klazz){
+static void s3jni_call_xDestroy(JNIEnv * const env, jobject jObj){
if(jObj){
- jmethodID method;
- if(!klazz){
- klazz = (*env)->GetObjectClass(env, jObj);
- assert(klazz);
- }
- method = (*env)->GetMethodID(env, klazz, "xDestroy", "()V");
+ jclass const klazz = (*env)->GetObjectClass(env, jObj);
+ jmethodID method = (*env)->GetMethodID(env, klazz, "xDestroy", "()V");
+
+ UNREF_L(klazz);
if(method){
s3jni_incr( &SJG.metrics.nDestroy );
(*env)->CallVoidMethod(env, jObj, method);
EXCEPTION_CLEAR;
}
}else{
+ /* Non-fatal. */
EXCEPTION_CLEAR;
}
}
/*
** Removes any Java references from s and clears its state. If
-** doXDestroy is true and s->klazz and s->jObj are not NULL, s->jObj's
+** doXDestroy is true and s->jObj is not NULL, s->jObj's
** s is passed to s3jni_call_xDestroy() before any references are
** cleared. It is legal to call this when the object has no Java
** references.
*/
static void S3JniHook_unref(JNIEnv * const env, S3JniHook * const s, int doXDestroy){
- if(doXDestroy && s->klazz && s->jObj){
- s3jni_call_xDestroy(env, s->jObj, s->klazz);
+ if(doXDestroy && s->jObj){
+ s3jni_call_xDestroy(env, s->jObj);
}
UNREF_G(s->jObj);
- UNREF_G(s->klazz);
memset(s, 0, sizeof(*s));
}
static int S3JniAutoExtension_init(JNIEnv *const env,
S3JniAutoExtension * const ax,
jobject const jAutoExt){
- jclass klazz;
- klazz = (*env)->GetObjectClass(env, jAutoExt);
- if(!klazz){
- S3JniAutoExtension_clear(env, ax);
- return SQLITE_ERROR;
- }
+ jclass const klazz = (*env)->GetObjectClass(env, jAutoExt);
+
ax->midFunc = (*env)->GetMethodID(env, klazz, "xEntryPoint",
"(Lorg/sqlite/jni/sqlite3;)I");
- EXCEPTION_WARN_IGNORE;
UNREF_L(klazz);
+ EXCEPTION_WARN_IGNORE;
if(!ax->midFunc){
MARKER(("Error getting xEntryPoint(sqlite3) from AutoExtension object."));
S3JniAutoExtension_clear(env, ax);
if(!pNC->fidAggCtx){
MUTEX_NPH_ENTER;
if(!pNC->fidAggCtx){
- pNC->fidAggCtx = (*env)->GetFieldID(env, pNC->klazz,
- "aggregateContext", "J");
+ pNC->fidAggCtx = (*env)->GetFieldID(env, pNC->klazz, "aggregateContext", "J");
EXCEPTION_IS_FATAL("Cannot get sqlite3_contex.aggregateContext member.");
}
MUTEX_NPH_LEAVE;
typedef struct S3JniUdf S3JniUdf;
struct S3JniUdf {
jobject jObj /* SQLFunction instance */;
- jclass klazz /* jObj's class */;
char * zFuncName /* Only for error reporting and debug logging */;
enum UDFType type;
/** Method IDs for the various UDF methods. */
"(Lorg/sqlite/jni/sqlite3_context;[Lorg/sqlite/jni/sqlite3_value;)V";
const char * zFV = /* signature for xFinal, xValue */
"(Lorg/sqlite/jni/sqlite3_context;)V";
+ jclass const klazz = (*env)->GetObjectClass(env, jObj);
+
memset(s, 0, sizeof(S3JniUdf));
s->jObj = REF_G(jObj);
- s->klazz = REF_G((*env)->GetObjectClass(env, jObj));
#define FGET(FuncName,FuncType,Field) \
- s->Field = (*env)->GetMethodID(env, s->klazz, FuncName, FuncType); \
+ s->Field = (*env)->GetMethodID(env, klazz, FuncName, FuncType); \
if(!s->Field) (*env)->ExceptionClear(env)
FGET("xFunc", zFSI, jmidxFunc);
FGET("xStep", zFSI, jmidxStep);
FGET("xValue", zFV, jmidxValue);
FGET("xInverse", zFSI, jmidxInverse);
#undef FGET
+ UNREF_L(klazz);
if(s->jmidxFunc) s->type = UDF_SCALAR;
else if(s->jmidxStep && s->jmidxFinal){
s->type = s->jmidxValue ? UDF_WINDOW : UDF_AGGREGATE;
LocalJniGetEnv;
if(env){
//MARKER(("UDF cleanup: %s\n", s->zFuncName));
- s3jni_call_xDestroy(env, s->jObj, s->klazz);
+ s3jni_call_xDestroy(env, s->jObj);
UNREF_G(s->jObj);
- UNREF_G(s->klazz);
}
sqlite3_free(s->zFuncName);
sqlite3_free(s);
/* Same object - this is a no-op. */
return 0;
}
+ jclass klazz;
S3JniHook_unref(env, pHook, 1);
pHook->jObj = REF_G(jBusy);
- pHook->klazz = REF_G((*env)->GetObjectClass(env, jBusy));
- pHook->midCallback = (*env)->GetMethodID(env, pHook->klazz, "xCallback", "(I)I");
+ klazz = (*env)->GetObjectClass(env, jBusy);
+ pHook->midCallback = (*env)->GetMethodID(env, klazz, "xCallback", "(I)I");
+ UNREF_L(klazz);
IFTHREW {
S3JniHook_unref(env, pHook, 0);
rc = SQLITE_ERROR;
klazz = (*env)->GetObjectClass(env, jHook);
xCallback = (*env)->GetMethodID(env, klazz, "xCollationNeeded",
"(Lorg/sqlite/jni/sqlite3;ILjava/lang/String;)I");
+ UNREF_L(klazz);
IFTHREW {
rc = s3jni_db_exception(env, ps, SQLITE_MISUSE,
"Cannot not find matching callback on "
xCallback = (*env)->GetMethodID(env, klazz,
isCommit ? "xCommitHook" : "xRollbackHook",
isCommit ? "()I" : "()V");
+ UNREF_L(klazz);
IFTHREW {
EXCEPTION_REPORT;
EXCEPTION_CLEAR;
S3JniHook tmpHook;
S3JniHook * const hook = &tmpHook;
S3JniHook * const hookOld = & SJG.hooks.sqllog;
+ jclass klazz;
int rc = 0;
if( !jLog ){
S3JniHook_unref(env, hookOld, 0);
if( hookOld->jObj && (*env)->IsSameObject(env, jLog, hookOld->jObj) ){
return 0;
}
- hook->klazz = REF_G( (*env)->GetObjectClass(env, jLog) );
- hook->midCallback = (*env)->GetMethodID(env, hook->klazz, "xSqllog",
+ klazz = (*env)->GetObjectClass(env, jLog);
+ hook->midCallback = (*env)->GetMethodID(env, klazz, "xSqllog",
"(Lorg/sqlite/jni/sqlite3;"
"Ljava/lang/String;"
"I)V");
+ UNREF_L(klazz);
if( !hook->midCallback ){
EXCEPTION_WARN_IGNORE;
S3JniHook_unref(env, hook, 0);
klazz = (*env)->GetObjectClass(env, oCollation);
pHook->midCallback = (*env)->GetMethodID(env, klazz, "xCompare",
"([B[B)I");
+ UNREF_L(klazz);
IFTHREW{
- EXCEPTION_REPORT;
+ UNREF_L(klazz);
return s3jni_db_error(ps->pDb, SQLITE_ERROR,
"Could not get xCompare() method for object.");
}
JSTR_RELEASE(name, zName);
if( 0==rc ){
pHook->jObj = REF_G(oCollation);
- pHook->klazz = REF_G(klazz);
}else{
S3JniHook_unref(env, pHook, 1);
}
"JJ)V")
: (*env)->GetMethodID(env, klazz, "xUpdateHook",
"(ILjava/lang/String;Ljava/lang/String;J)V");
+ UNREF_L(klazz);
IFTHREW {
EXCEPTION_CLEAR;
s3jni_db_error(ps->pDb, SQLITE_ERROR,
}
klazz = (*env)->GetObjectClass(env, jProgress);
xCallback = (*env)->GetMethodID(env, klazz, "xCallback", "()I");
+ UNREF_L(klazz);
IFTHREW {
EXCEPTION_CLEAR;
s3jni_db_error(ps->pDb, SQLITE_ERROR,
return (jint)sqlite3_set_authorizer( ps->pDb, 0, 0 );
}else{
int rc = 0;
+ jclass klazz;
if( pHook->jObj ){
if( (*env)->IsSameObject(env, pHook->jObj, jHook) ){
/* Same object - this is a no-op. */
S3JniHook_unref(env, pHook, 0);
}
pHook->jObj = REF_G(jHook);
- pHook->klazz = REF_G((*env)->GetObjectClass(env, jHook));
- pHook->midCallback = (*env)->GetMethodID(env, pHook->klazz,
+ klazz = (*env)->GetObjectClass(env, jHook);
+ pHook->midCallback = (*env)->GetMethodID(env, klazz,
"xAuth",
"(I"
"Ljava/lang/String;"
"Ljava/lang/String;"
"Ljava/lang/String;"
")I");
+ UNREF_L(klazz);
IFTHREW {
S3JniHook_unref(env, pHook, 0);
return s3jni_db_error(ps->pDb, SQLITE_ERROR,
klazz = (*env)->GetObjectClass(env, jTracer);
ps->hooks.trace.midCallback = (*env)->GetMethodID(env, klazz, "xCallback",
"(ILjava/lang/Object;Ljava/lang/Object;)I");
+ UNREF_L(klazz);
IFTHREW {
EXCEPTION_CLEAR;
return s3jni_db_error(ps->pDb, SQLITE_ERROR,
*/
typedef struct {
jobject jObj /* functor instance */;
- jclass klazz /* jObj's class */;
jobject jUserData /* 2nd arg to JNI binding of
xCreateFunction(), ostensibly the 3rd arg
to the lib-level xCreateFunction(), except
LocalJniGetEnv;
if(env){
/*MARKER(("FTS5 aux function cleanup: %s\n", s->zFuncName));*/
- s3jni_call_xDestroy(env, s->jObj, s->klazz);
+ s3jni_call_xDestroy(env, s->jObj);
UNREF_G(s->jObj);
- UNREF_G(s->klazz);
UNREF_G(s->jUserData);
}
sqlite3_free(s->zFuncName);
static Fts5JniAux * Fts5JniAux_alloc(JNIEnv * const env, jobject jObj){
Fts5JniAux * s = sqlite3_malloc(sizeof(Fts5JniAux));
if(s){
+ jclass klazz;
memset(s, 0, sizeof(Fts5JniAux));
s->jObj = REF_G(jObj);
- s->klazz = REF_G((*env)->GetObjectClass(env, jObj));
- s->jmid = (*env)->GetMethodID(env, s->klazz, "xFunction",
+ klazz = (*env)->GetObjectClass(env, jObj);
+ s->jmid = (*env)->GetMethodID(env, klazz, "xFunction",
"(Lorg/sqlite/jni/Fts5ExtensionApi;"
"Lorg/sqlite/jni/Fts5Context;"
"Lorg/sqlite/jni/sqlite3_context;"
"[Lorg/sqlite/jni/sqlite3_value;)V");
+ UNREF_L(klazz);
IFTHREW{
EXCEPTION_REPORT;
EXCEPTION_CLEAR;
S3JniFts5AuxData * const p = x;
if(p->jObj){
LocalJniGetEnv;
- s3jni_call_xDestroy(env, p->jObj, 0);
+ s3jni_call_xDestroy(env, p->jObj);
UNREF_G(p->jObj);
}
sqlite3_free(x);
Fts5PhraseIter const * const pSrc,
jobject jIter){
S3JniGlobalType * const g = &S3JniGlobal;
- assert(g->fts5.jPhraseIter.klazz);
+ assert(g->fts5.jPhraseIter.fidA);
(*env)->SetLongField(env, jIter, g->fts5.jPhraseIter.fidA, (jlong)pSrc->a);
EXCEPTION_IS_FATAL("Cannot set Fts5PhraseIter.a field.");
(*env)->SetLongField(env, jIter, g->fts5.jPhraseIter.fidB, (jlong)pSrc->b);
static void s3jni_phraseIter_JToN(JNIEnv *const env, jobject jIter,
Fts5PhraseIter * const pDest){
S3JniGlobalType * const g = &S3JniGlobal;
- assert(g->fts5.jPhraseIter.klazz);
+ assert(g->fts5.jPhraseIter.fidA);
pDest->a =
(const unsigned char *)(*env)->GetLongField(env, jIter, g->fts5.jPhraseIter.fidA);
EXCEPTION_IS_FATAL("Cannot get Fts5PhraseIter.a field.");
Fts5ExtDecl;
Fts5PhraseIter iter;
int iCol = 0, iOff = 0;
- if(!SJG.fts5.jPhraseIter.klazz) return /*SQLITE_MISUSE*/;
s3jni_phraseIter_JToN(env, jIter, &iter);
fext->xPhraseNext(PtrGet_Fts5Context(jCtx), &iter, &iCol, &iOff);
OutputPointer_set_Int32(env, jOutCol, iCol);
Fts5ExtDecl;
Fts5PhraseIter iter;
int iCol = 0;
- if(!SJG.fts5.jPhraseIter.klazz) return /*SQLITE_MISUSE*/;
s3jni_phraseIter_JToN(env, jIter, &iter);
fext->xPhraseNextColumn(PtrGet_Fts5Context(jCtx), &iter, &iCol);
OutputPointer_set_Int32(env, jOutCol, iCol);
s.midCallback = (*env)->GetMethodID(env, klazz, "xCallback",
"(Lorg.sqlite.jni.Fts5ExtensionApi;"
"Lorg.sqlite.jni.Fts5Context;)I");
+ UNREF_L(klazz);
EXCEPTION_IS_FATAL("Could not extract xQueryPhraseCallback.xCallback method.");
return (jint)fext->xQueryPhrase(PtrGet_Fts5Context(jFcx), iPhrase, &s,
s3jni_xQueryPhrase);
if(jAux){
/* Emulate how xSetAuxdata() behaves when it cannot alloc
** its auxdata wrapper. */
- s3jni_call_xDestroy(env, jAux, 0);
+ s3jni_call_xDestroy(env, jAux);
}
return SQLITE_NOMEM;
}
s.jFcx = jFcx;
s.fext = fext;
s.midCallback = (*env)->GetMethodID(env, klazz, "xToken", "(I[BII)I");
+ UNREF_L(klazz);
IFTHREW {
EXCEPTION_REPORT;
EXCEPTION_CLEAR;
SJG.g.oCharsetUtf8 =
REF_G((*env)->GetStaticObjectField(env, klazz, fUtf8));
EXCEPTION_IS_FATAL("Error getting reference to StandardCharsets.UTF_8.");
+ UNREF_L(klazz);
}
#ifdef SQLITE_ENABLE_FTS5
klazz = (*env)->FindClass(env, "org/sqlite/jni/Fts5PhraseIter");
EXCEPTION_IS_FATAL("Error getting reference to org.sqlite.jni.Fts5PhraseIter.");
- SJG.fts5.jPhraseIter.klazz = REF_G(klazz);
SJG.fts5.jPhraseIter.fidA = (*env)->GetFieldID(env, klazz, "a", "J");
EXCEPTION_IS_FATAL("Cannot get Fts5PhraseIter.a field.");
- SJG.fts5.jPhraseIter.fidB = (*env)->GetFieldID(env, klazz, "a", "J");
+ SJG.fts5.jPhraseIter.fidB = (*env)->GetFieldID(env, klazz, "b", "J");
EXCEPTION_IS_FATAL("Cannot get Fts5PhraseIter.b field.");
+ UNREF_L(klazz);
#endif
SJG.envCache.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);