Передача одного и того же вида поверхности Android в код C ++ через jni приводит к различным значениям

//Android
SurfaceView SW;

function doSomthing()
{
startPreview(SW);
snapShot(SW);
}

//C++
startPreview(jobject window)
{
TDebug("w1 = %u",window);
}

snapshot(jobject window)
{
TDebug("w2 = %u",window);
}

Процесс преобразования параметров осуществляется следующим образом.

SurfaceView ->Object->Jobject(jni)->void*(C++)

Почему w1 != w2?


Все методы JNI принимают как локальные, так и глобальные ссылки в качестве аргументов. Ссылки на один и тот же объект могут иметь разные значения. Например, возвращаемые значения от последовательных вызовов NewGlobalRef для одного и того же объекта могут отличаться. Чтобы увидеть, ссылаются ли две ссылки на один и тот же объект, вы должны использовать функцию IsSameObject. Никогда не сравнивайте ссылки с == в нативном коде.

Одним из следствий этого является то, что вы не должны предполагать, что ссылки на объекты являются постоянными или уникальными в собственном коде. 32-битное значение, представляющее объект, может отличаться от одного вызова метода к другому, и возможно, что два разных объекта могут иметь одно и то же 32-битное значение при последовательных вызовах. Не используйте значения заданий в качестве ключей.

1

Решение

Так как jobject window это местная справка. Если вы хотите сравнить две ссылки на объекты, указывают ли они на один и тот же объект, вы должны использовать JNIEnv* а также IsSameObject его функция-член

static jobject window1=nullptr;
static jobject window2=nullptr;

Java_your_prefix_class_startPreview(JNIEnv *env,jobject thiz,jobject window){
window1=env->NewGlobalRef(window);
}

Java_your_prefix_class_snapshot(JNIEnv *env,jobject thiz,jobject window){
window2=env->NewGlobalRef(window);

TDebug("windows are equal = %d", env->IsSameObject(window1, window2));
}

Больше

Я столкнулся с этой проблемой не так давно. jobjectПереданные в функции JNI могут иметь разные значения, даже если они указывают на одни и те же объекты. Это происходит потому, что у JVM есть некоторый пул локальных объектов, и каждый тик очищает все локальные объекты для GC, если у них нет глобальных ссылок. Поэтому, если вы хотите сохранить указатель на jobject в своем коде C ++, вам нужно создать глобальную ссылку из локальной. И, пожалуйста, не забудьте выпустить env->DeleteGlobalRef как только вы закончите с вашим объектом или ваша программа будет иметь утечки памяти в противном случае.

0

Другие решения

Других решений пока нет …