Android扩展JNI本地参考表

时间:2013-06-10 21:50:57

标签: java android c++ memory java-native-interface

我有很多要在c ++上创建的对象并将其发送到java,我正在使用env->DeleteLocalRef(obj);但是我收到以下错误:

06-10 18:43:56.976: E/dalvikvm(11536): JNI ERROR (app bug): local reference table overflow (max=512)
06-10 18:43:56.980: W/dalvikvm(11536): JNI local reference table (0x4d9c0b28) dump:
06-10 18:43:56.980: W/dalvikvm(11536):   Last 10 entries (of 512):
06-10 18:43:56.980: W/dalvikvm(11536):       511: 0x412bab68 java.lang.Class<la.jurema.moovebike.models.RoutePoint>
06-10 18:43:56.980: W/dalvikvm(11536):       510: 0x412bab68 java.lang.Class<la.jurema.moovebike.models.RoutePoint>
06-10 18:43:56.980: W/dalvikvm(11536):       509: 0x40e2a2a8 la.jurema.moovebike.models.RoutePoint[] (20 elements)
06-10 18:43:56.980: W/dalvikvm(11536):       508: 0x412bab68 java.lang.Class<la.jurema.moovebike.models.RoutePoint>
06-10 18:43:56.980: W/dalvikvm(11536):       507: 0x412bab68 java.lang.Class<la.jurema.moovebike.models.RoutePoint>
06-10 18:43:56.980: W/dalvikvm(11536):       506: 0x412de350 java.lang.Class<la.jurema.moovebike.models.BikeRoute>
06-10 18:43:56.980: W/dalvikvm(11536):       505: 0x412bab68 java.lang.Class<la.jurema.moovebike.models.RoutePoint>
06-10 18:43:56.980: W/dalvikvm(11536):       504: 0x412bab68 java.lang.Class<la.jurema.moovebike.models.RoutePoint>
06-10 18:43:56.980: W/dalvikvm(11536):       503: 0x412bab68 java.lang.Class<la.jurema.moovebike.models.RoutePoint>
06-10 18:43:56.980: W/dalvikvm(11536):       502: 0x412bab68 java.lang.Class<la.jurema.moovebike.models.RoutePoint>
06-10 18:43:56.980: W/dalvikvm(11536):   Summary:
06-10 18:43:56.980: W/dalvikvm(11536):       505 of java.lang.Class (7 unique instances)
06-10 18:43:56.980: W/dalvikvm(11536):         3 of java.lang.String (3 unique instances)
06-10 18:43:56.980: W/dalvikvm(11536):         1 of java.lang.String[] (2 elements)
06-10 18:43:56.980: W/dalvikvm(11536):         1 of la.jurema.moovebike.network.DataDownloadResponseAbstract
06-10 18:43:56.980: W/dalvikvm(11536):         1 of la.jurema.moovebike.models.BikeRoute[] (15 elements)
06-10 18:43:56.980: W/dalvikvm(11536):         1 of la.jurema.moovebike.models.RoutePoint[] (20 elements)
06-10 18:43:56.980: E/dalvikvm(11536): Failed adding to JNI local ref table (has 512 entries)

我不知道这个java.lang.Class是什么意思......我怎么能解决这个问题?增加参考表?或者我没有删除什么?

3 个答案:

答案 0 :(得分:6)

您需要删除对类和对象的本地引用。

答案 1 :(得分:4)

看起来你正在获得java.lang.Class的大量实例。获取这些内容的最常见方法是致电FindClass。 &lt;&gt;中的名称尖括号是查找的类的名称,因此您应该查找在RoutePointBikeRoute上进行查找的位置。

FindClass可能相当昂贵,因此对于经常使用的类,您希望在初始化期间调用它并缓存结果(作为全局引用)供以后使用。

如果您在循环中运行,最好显式删除返回的任何对象的本地引用。 Dalvik中无法将本地参考表扩展到512个以上的条目。

另请参阅JNI Tips文档。

答案 2 :(得分:0)

我发现以下技术有用,如果不是非常冗长,我创建了一个名为Guardian的类,如下所示:

/*
 * Guardian.h
 *
 *  Created on: Jul 14, 2014
 *      Author: yaturner
 */
#ifndef GUARDIAN_H_
#define GUARDIAN_H_

#define GLOGD(...) __android_log_print(ANDROID_LOG_DEBUG, tagName, __VA_ARGS__ )

{

class Guardian
{
private:
    char* funcName;
    char* tagName;

public:
    Guardian(const char*, const char*);
    virtual ~Guardian();
};

#endif /* GUARDIAN_H_ */

/*
 * Guardian.cpp
 *
 *  Created on: Jul 14, 2014
 *      Author: yaturner
 */
#include "Guardian.h"

Guardian(const char* func, const char* tag)
{
    int len = strlen(func);
    funcName = new char[len+1];
    strcpy(funcName, func);
    len = strlen(func);
    tagName = new char[len+1];
    strcpy(tagName, tag);
    GLOGD("Entering %s", funcName);
}

~Guardian()
{
    GLOGD("Exiting %s", funcName);
    dumpLocalRefTable();
    free(funcName);
    free(tagName);

}

void dumpLocalRefTable()
{
    JNIEnv* env = preamble(); 
    jclass vm_class = env->FindClass("dalvik/system/VMDebug");
    jmethodID dump_mid = env->GetStaticMethodID( vm_class, "dumpReferenceTables", "()V" );
    env->CallStaticVoidMethod( vm_class, dump_mid );

    env->DeleteLocalRef(vm_class);
}

然后在我的每个JNI方法的开头,我实现了Guardian类,我得到的是一个带有每个方法入口和出口以及ref表的大规模logcat。通过检查日志,我可以查找表中的更改并确定导致它们的方法。痛苦但有效。