JNI:错误JNI本地引用表中的最后10个条目。

时间:2014-03-17 09:47:37

标签: sqlite java-native-interface

我尝试开发Native sqlite Lib,这将有助于访问shA256加密的sqlite db。查询结果不大但是如果查询结果记录计数多,则JNI返回错误“本地引用表溢出512条目”。请查看下面的代码示例。

jobjectArray rows = NULL;

sqlite3_stmt *statement;

if(sqlite3_prepare_v2(db, sdbquery, -1, &statement, 0) == SQLITE_OK)
{
    int cols = sqlite3_column_count(statement);
    int result = 0;
    jboolean flag = JNI_TRUE;
    int crow=0;
    jclass stringClass= (*env)->FindClass(env, "java/lang/String");
    while(1)
    {
        result = sqlite3_step(statement);
        LOGV("RESULT COUNT : %d\n", result);
        if(result == SQLITE_ROW)
        {
            jobjectArray row = (*env)->NewObjectArray(env, cols, stringClass, 0);
            int col;
            for(col=0;col<cols;col++)
            {
                jstring s = (const char*)sqlite3_column_text(statement, col);

                /*jstring valStr;
                if (val == NULL) {
                    valStr = (*env)->NewStringUTF(env, "");
                } else {
                    valStr = (*env)->NewStringUTF(env, val);
                }*/
                //(*env)->SetObjectArrayElement(env, row, col, valStr);
                (*env)->SetObjectArrayElement(env, row, col, s);
                (*env)->DeleteLocalRef(env,s);
                //(*env)->ReleaseStringUTFChars(env, valStr,val);
                //(*env)->DeleteLocalRef(env,valStr);

            }
            if(flag == JNI_TRUE) {
                flag = JNI_FALSE;
                rows = (*env)->NewObjectArray(env, count_rows, (*env)->GetObjectClass(env, row), 0);
            }
            (*env)->SetObjectArrayElement(env, rows, crow, row);
            (*env)->DeleteLocalRef(env,row);
            crow++;
        }
        else
        {
            break;   
        }
    }
    sqlite3_finalize(statement);
}else{
    LOGV("SQL error : %s\n", sqlite3_errmsg(db));
    sqlite3_free(zErrMsg);
    sqlite3_close(db);
    return NULL;
}

(*env)->ReleaseStringUTFChars(env, dbquery, sdbquery);
(*env)->ReleaseStringUTFChars(env, dbpath, sdbString);
(*env)->ReleaseStringUTFChars(env, dbkey, sdbkey);

sqlite3_close(db);
return rows;

1 个答案:

答案 0 :(得分:0)

我无法看到如何使用简单的C强制转换来构造jstring对象。这一行:

jstring s = (const char*)sqlite3_column_text(statement, col);

导致内存损坏,imho。

您应该使用:

const char* val = sqlite3_column_text(statement, col);
jstring valStr;
if (val == NULL) {
   valStr = (*env)->NewStringUTF(env, "");
} else {
   valStr = (*env)->NewStringUTF(env, val);
}

请务必在SetObjectArrayElement来电后将字符串释放为:

(*env)->ReleaseStringUTFChars(env, valStr,val);
(*env)->DeleteLocalRef(env,valStr);

当您查询类或列数组值时,您不会释放它。

应该是:

jclass rowClass = (*env)->GetObjectClass(env, row);
rows = (*env)->NewObjectArray(env, count_rows, rowClass , 0);
(*env)->DeleteLocalRef(env,rowClass);

此外,正如评论中所见,您应该仔细检查count_rows的使用情况。