//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-битное значение при последовательных вызовах. Не используйте значения заданий в качестве ключей.
Так как 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
как только вы закончите с вашим объектом или ваша программа будет иметь утечки памяти в противном случае.
Других решений пока нет …