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 以分配对象。
根据 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 以分配对象。