简体   繁体   中英

Android Expand JNI Local Reference Table

I have a lot of objects to create on c++ and send it to java, I'm using the env->DeleteLocalRef(obj); but I'm getting the following error:

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)

I dont know what means this java.lang.Class ... how I can solve this? Increase the reference table? Or what I'm not deleting?

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

It looks like you're getting lots of instances of java.lang.Class . The most common way to get these is by calling FindClass . The name in the <> angle brackets is the name of the class that was looked up, so you should be looking for places where you do a lookup on RoutePoint or BikeRoute .

FindClass can be fairly expensive, so for frequently-used classes you want to call that during initialization and cache the result (as a global reference) for later use.

If you're running in a loop, it's a good idea to explicitly delete the local reference for any object returned. Expanding the local reference table beyond 512 entries isn't possible in Dalvik.

See also the JNI Tips document.

I found the following technique useful if not horribly verbose, I created a class called Guardian as follows:

/*
 * 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_ */

and

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

}

and

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

Then at the beginning of each of my JNI methods I instanciated the Guardian class, what I got was a massive logcat with each method entry and exit plus the ref table. By examining the log I could look for changes in the table and determine what method caused them. Painful but it worked.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM