4

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?

fadden
  • 51,356
  • 5
  • 116
  • 166
ademar111190
  • 14,215
  • 14
  • 85
  • 114
  • It means you have more references in the current frame than will fit. You can call `(*env)->PushLocalFrame(env, N)` to allocate more space before calling the code that actually generates the references. You should try to free local references whenever you are able as well. – technomage Jun 10 '13 at 22:11
  • @technomage I'm freeing all local reference as possible, but i really have a lot of instances.... how i can use PushLocalFrame? for example to use 1024 also 512 of memory? – ademar111190 Jun 10 '13 at 22:16
  • 1
    Surround your "allocating" code with `PushLocalFrame(env, 2048)` and `PopLocalFrame(env)`, then you won't have to delete individual references. – technomage Jun 11 '13 at 08:09

3 Answers3

5

You need to delete local references to classes as well as to objects.

user207421
  • 305,947
  • 44
  • 307
  • 483
4

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.

fadden
  • 51,356
  • 5
  • 116
  • 166
0

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.

user330844
  • 872
  • 1
  • 12
  • 12