【问题标题】:Android Expand JNI Local Reference TableAndroid 扩展 JNI 本地引用表
【发布时间】:2013-06-06 16:09:02
【问题描述】:

我有很多对象要在 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 是什么意思...我该如何解决这个问题?增加参考表?或者我没有删除什么?

【问题讨论】:

  • 这意味着您在当前框架中的引用超出了容纳范围。在调用实际生成引用的代码之前,您可以调用(*env)-&gt;PushLocalFrame(env, N) 分配更多空间。你也应该尽可能地释放本地引用。
  • @technomage 我正在尽可能地释放所有本地引用,但我确实有很多实例......我如何使用 PushLocalFrame?例如使用 1024 和 512 的内存?
  • PushLocalFrame(env, 2048)PopLocalFrame(env) 包围您的“分配”代码,这样您就不必删除单个引用。

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


【解决方案1】:

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

【讨论】:

  • 你说的是“jclass”引用?我是怎么做到的?
  • 与对象相同,使用 DeleteLocalRef()。一个 jclass 实际上是一个作业。
  • 如果你的模式是重复的,你也应该看看PushLocalFrame()PopLocalFrame()
【解决方案2】:

您似乎收到了很多java.lang.Class 的实例。最常用的方法是调用FindClass。 尖括号中的名称是被查找的类的名称,因此您应该寻找在RoutePointBikeRoute 上进行查找的地方。

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

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

另请参阅JNI Tips 文档。

【讨论】:

    【解决方案3】:

    我发现以下技术非常有用,如果不是非常冗长,我创建了一个名为 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 类,我得到的是一个巨大的 logcat,其中包含每个方法的入口和出口以及 ref 表。通过检查日志,我可以查找表中的更改并确定导致它们的方法。很痛苦,但它奏效了。

    【讨论】:

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