Search code examples
javac++cjava-native-interfaceclang

How to fix JNI crash on env->NewObject?


I'm trying to use Clang via JNI (Clang C-API). One moment after few iteractions it just stop creating new objects and crashes:

map method 0 args: create Method instance 0x7fa26ba23c90 0x7fa26ba2a0c0 libclang: crash detected during indexing source file: { 'source_filename' : '/Users/asmirnov/Documents/dev/src/clang_jni/mac/test/TestFile.h'
'command_line_args' : ['-c', '-x', 'c++'], 'unsaved_files' : [],
'options' : 0, }

The code is pretty straight-forward:

mapMethod(JNIEnv *env, const CXIdxDeclInfo *info) {

    debug("map method");

    int numArgs = clang_Cursor_getNumArguments(info->cursor);
    debug("  %i args:", numArgs);

    debug("create Method instance %p %p", MethodClass, MethodConstructor);
    jobject result = env->NewObject(MethodClass, MethodConstructor);

    debug("create Method  params instance");

Method class and constructor is found and registered as globals correctly (seems to be) and it works few iterations:

// method
    MethodClass = (jclass)env->NewGlobalRef(env->FindClass("name/antonsmirnov/clang/dto/index/Method"));
    debug(MethodClass != NULL ? "found MethodClass" : "not found MethodClass");

    MethodConstructor = env->GetMethodID(MethodClass, "<init>", "()V");
    debug(MethodConstructor != NULL ? "found MethodConstructor" : "not found MethodConstructor");

I've read some "jni tips and tricks" articles and tried to env->DeleteLocalRef and make local references count too big just to try, but no result:

// magic 
    jint ensureResult = env->EnsureLocalCapacity(1024);
    debug("ensure result %i", ensureResult);

    jint pushResult = env->PushLocalFrame(1024);
    debug("push result %i", pushResult);

Clang is hijacking exception so i can't see the real reason. The problem happens after few iterations as i said so it seems to be some limit exceeded problem or smth.

What is wrong?

UPDATE: I've done some research and i found that if i delete some local vars before then i can get one iteration more and one object instance more. So it makes me feel that it's using 16 local vars indeed and ignore my EnsureLocalCapacity invocation. Where should it be done?


Solution

  • Fixed using EnsureLocalCapacity in JNI_OnLoad() (did not work in each native method call).