Return 来自 JNI 的大对象数组?

Return a big object array from JNI?

根据 doc

jint EnsureLocalCapacity(JNIEnv *env, jint capacity);

Ensures that at least a given number of local references can be created in the current thread. Returns 0 on success; otherwise returns a negative number and throws an OutOfMemoryError.

Before it enters a native method, the VM automatically ensures that at least 16 local references can be created.

For backward compatibility, the VM allocates local references beyond the ensured capacity. (As a debugging support, the VM may give the user warnings that too many local references are being created. In the JDK, the programmer can supply the -verbose:jni command line option to turn on these messages.) The VM calls FatalError if no more local references can be created beyond the ensured capacity.

似乎对可以创建的本地引用的数量有一些限制。

我有以下代码 return 一个大对象数组,这会导致创建大量本地引用。这是否意味着这很容易达到极限? -- 文档默认为 16。

extern "C" JNIEXPORT
jobjectArray JNICALL Java_MessageQueueInterop_receive(JNIEnv * env, jobject this_obj, jclass cls)
{
    int count = 99999;
    jobjectArray ret = env->NewObjectArray( count, cls, NULL);
    if( ret ){
        for( int i = 0; i < count; i++ ) {
            jobject obj = env->NewObject( cls, constructor);
            if( obj ){
            env->SetIntField( obj, fieldID1, 2);

            jstring str = env->NewStringUTF("XXX");
            if( str )
                env->SetObjectField( obj, fieldID2, str);

            env->SetObjectArrayElement( ret, i, obj);
            }
        }
    }
    return ret;
}

如何延长限制?

那么100,000 > 16 所以你肯定有麻烦了。

您可以尝试 PushLocalFrame() and PopLocalFrame() 的组合,如下所示:

extern "C" JNIEXPORT
jobjectArray JNICALL Java_MessageQueueInterop_receive(JNIEnv * env, jobject this_obj, jclass cls)
{
    int count = 99999;
    jobjectArray ret = env->NewObjectArray( count, cls, NULL);
    if( ret ){
        for( int i = 0; i < count; i++ ) {
            PushLocalFrame(env, 1); // TODO error checking required here
            jobject obj = env->NewObject( cls, constructor);
            if( obj ){
                env->SetIntField( obj, fieldID1, 2);
                jstring str = env->NewStringUTF("XXX");
                if( str )
                    env->SetObjectField( obj, fieldID2, str);
            }
            obj = PopLocalFrame(env, obj);
            env->SetObjectArrayElement( ret, i, obj);
        }
    }
    return ret;
}

E&OE。可能有效,也可能无效。 [再想想,可能不是。]

让调用者提供一个 LinkedList 可能会更好,这样您就不必分配这个巨大的数组,也许还有一个调用循环,这样您一次只能从本机队列中添加一个元素在 JNI 内部,或者回调到 Java 以分配对象。