0

I am experiencing a strange problem. I have a JNI code (very simplified for clarity) that goes as follows

void Foo::Bar(int count)
{
....
    jclass javaClass1 = (jclass)env->FindClass("MyJavaClass1");
    jmethodID constrObject1 = env->GetMethodID(javaClass1, "<init>", "()V");
...
    jclass javaClassN = (jclass)env->FindClass("MyJavaClassN");
    jmethodID constrObjectN = env->GetMethodID(javaClassN, "<init>", "()V");
    for (int i = 0; i < count; i++)
    {
        env->PushLocalFrame(256 ) ;
        jobject jniObject1 = env->NewObject(javaClass1, constrObject1);
...
        jobject jniObjectN = env->NewObject(javaClassN, constrObjectN);
        doSomething(<some objects created above>);
        doSomethingElse(<some objects created above>);
        doSomethingThird(<some objects created above>);
        env->PopLocalFrame(0);
    }
}

This code is working fine when compiled with CLang for Android API 27 but crashes when compiled with gcc for Android API 21 with the error

01-01 03:23:26.714 715 715 F DEBUG : signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- 
01-01 03:23:26.736 715 715 F DEBUG : Abort message: 'art/runtime/indirect_reference_table.cc:115] JNI ERROR (app bug): local reference table overflow (max=512)' 

I know what this error means and use PushLocalFrame/PopLocalFrame to prevent it. What I am asking is: why this code works with CLang but doesn't work with gcc? Am I missing something? Or, probably, the issue is API 21 vs API 27?

I have found this question and this question, they look related to my problem, but they are old and probably irrelevant. I would be grateful for any pointers.

Flot2011
  • 4,601
  • 3
  • 44
  • 61
  • 1
    Code working with one compiler but not another is a typical sign of [*undefined behavior*](https://en.wikipedia.org/wiki/Undefined_behavior). And it doesn't have to be in the code where the crash happens. – Some programmer dude Apr 21 '19 at 10:57
  • Not sure it is the case. The whole JNI code is very straightforward. I get some data from C++ and pass it to Java. No complicated algorithms, no threads, no ambiguous allocations. Got some objects, made corresponding Java objects for them, set their members, done. Back to Java. – Flot2011 Apr 21 '19 at 11:07
  • Can you not free each reference before it's variable goes out of scope? – Tom Blodget Apr 21 '19 at 20:44
  • I wish I could. They are all needed in various combinations. – Flot2011 Apr 21 '19 at 21:59
  • You can compile your library with the latest NDK (and Clang) even if you want to target API 21. Actually, there is little reason to compile the library separately for API 27, as long as it compiled for API 21. – Alex Cohn Apr 22 '19 at 04:22
  • I see absolutely no error checking. There's a good chance one of your calls back to the JVM fails for some reason and the code you posted would just continue on, ignoring the problem. That usually leads to the JVM failing as you're experiencing. Something could be tossing an exception, for example, or even one of your class lookups could be failing. – Andrew Henle Apr 22 '19 at 09:25
  • @AndrewHenle - as I said, the code is very simplified for clarity, I have error checking in place in the real code – Flot2011 Apr 22 '19 at 12:21
  • @AlexCohn - Yes, I can. But I am curious as to what is the reason for this problem – Flot2011 Apr 22 '19 at 12:24
  • what I suggested is a way to eliminate some factors, to help you find the root cause of the crash – Alex Cohn Apr 22 '19 at 13:57

0 Answers0