【问题标题】:JNI: error Last 10 entries in JNI local reference table.JNI: 错误 JNI 本地引用表中的最后 10 个条目。
【发布时间】:2014-03-17 09:47:37
【问题描述】:

我正在尝试开发 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;

【问题讨论】:

  • 这里有什么东西不能通过 JDBC 在 Java 中完成吗?
  • 不确定你在哪里填充count_rows,但是创建一个字符串数组对象的数组是你吹出本地引用计数的地方。

标签: sqlite java-native-interface


【解决方案1】:

我看不出如何使用简单的 C 转换构造 jstring 对象。行:

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

导致内存损坏,恕我直言。

你应该使用:

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);

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-06
    • 1970-01-01
    • 1970-01-01
    • 2012-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多