- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
//***** 新问题。 *****
当将结构传递给线程时,下面存在内存泄漏。不明白为什么,因为如果在主线程中直接调用线程内的代码不会泄漏内存。
class PeopleCounting{
// Class variables
Ptr<cv::BackgroundSubtractorMOG2> pMOG2 = cv::createBackgroundSubtractorMOG2(500, 16);
Mat maskBackgroundSubtracted = Mat(resizeDimension.height, resizeDimension.width, CV_8UC1);
// Thread creation code below, code called from main.
//Create thread
pthread_t threads;
pthread_attr_t attr;
void *status;
// Initialize and set thread joinable
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
// Creating thread data and initializing it
BackgroundSubstractionThreadData threadData = {CamImage, maskBackgroundSubtracted, pMOG2};
int rc;
rc = pthread_create(&threads, NULL, performBackgroundSubstraction, (void *)&threadData);
if (rc)
{
__android_log_print(ANDROID_LOG_ERROR, APPNAME, "Error: peopleCountingMainMono unable to create thread - %d",rc);
}
// free attribute and wait for the other threads
pthread_attr_destroy(&attr);
// ************** Do something else in main thread **************
// Join thread i.e. wait till completion of thread
rc = pthread_join(threads, &status);
if (rc)
{
__android_log_print(ANDROID_LOG_ERROR, APPNAME, "Error: peopleCountingMainMono unable to join - %d",rc);
}
// Using class variable **maskBackgroundSubtracted** and **pMOG2** for later use. **CamImage** (opencv mat) usually gets released automatically in general due to smart pointer implementation, not sure if it is the source of leak
}
// Note: Outside class
void *performBackgroundSubstraction(void *threadarg)
{
struct BackgroundSubstractionThreadData *my_data;
my_data = (struct BackgroundSubstractionThreadData *)threadarg;
Mat fgMask;
my_data->pMOG2F->apply(my_data->leftCamImage, fgMask, 0.002);
morphologyEx(fgMask, fgMask, MORPH_OPEN, getStructuringElement(MORPH_RECT, Size(3, 3)),Point(-1,-1),1);
morphologyEx(fgMask, fgMask, MORPH_CLOSE, getStructuringElement(MORPH_RECT, Size(11, 11)),Point(-1,-1),1);
threshold(fgMask, my_data->dst, 128, 255, THRESH_BINARY);
pthread_exit(NULL);
};
//***** 问题结束 ****
我有一个 NDK 库,它有一个返回 jobjectArray
的 JNI 函数在下面的代码中,我使用了一个静态全局 jPeopleCountArray,它通过循环填充了 jobject 并返回到 Java 调用方法。这个 JNI 函数通过我的 Java 代码中的循环一次又一次地调用,但一次只调用一个实例,因此允许全局返回对象。我通过遍历 jobject 数组并删除 jobjects 的本地引用,最后删除 jPeopleCountArray 的全局引用,在库使用结束时执行内存清理。内存清理仅在最后执行,因为迭代使用(但仅限单个实例)允许重用返回对象。
问题是当我通过 NewObjectArray 分配全局 jobjectArray 时。由于之前的调用,之前保留在 jobjectArray 中的所有 jobject 是否从内存中释放?
class PeopleCounting{
public:
static inline jobjectArray jPeopleCountArray = NULL;
static inline JNI_PEOPLECOUNT * jniPeopleCount = NULL;
// .... Rest of Code ...
}
// JNI function
PeopleCounting *obj = (PeopleCounting *) hEngineHandle;
obj->LoadJniPeopleCount(env);
Mat *pMatCGray = (Mat *) addrCamGray;
vector<PeopleSegment> peopleCountingFromContourRes = obj->peopleCountingMainMono(
*pMatCGray);
// ******** IMPORTANT BELOW *********
obj->jPeopleCountArray = env->NewObjectArray(peopleCountingFromContourRes.size(),
obj->jniPeopleCount->cls, NULL);
for (size_t i = 0; i < peopleCountingFromContourRes.size(); i++) {
jobject jPeopleCount = env->NewObject(obj->jniPeopleCount->cls,
obj->jniPeopleCount->constructortorID);
obj->FillPeopleCountValuesToJni(env, jPeopleCount, peopleCountingFromContourRes[i]);
env->SetObjectArrayElement(obj->jPeopleCountArray, i, jPeopleCount);
}
return obj->jPeopleCountArray;
// Memory cleanup at the end of library use.
PeopleCounting *obj = (PeopleCounting *) hEngineHandle;
if (obj->jPeopleCountArray != NULL){
__android_log_print(ANDROID_LOG_VERBOSE, APPNAME,
"Freeing memory of jobject array");
//https://www.ibm.com/developerworks/library/j-jni/index.html
int size = env->GetArrayLength(obj->jPeopleCountArray);
for(int i = 0; i < size; i++)
{
jobject row = env->GetObjectArrayElement(obj->jPeopleCountArray, i);
if(env->ExceptionOccurred()) {
break;
}
env->DeleteLocalRef(row);
}
env->DeleteGlobalRef(obj->jPeopleCountArray);
}
delete (PeopleCounting *)(hEngineHandle);
最佳答案
您的代码可能会耗尽非常有限的本地引用表(其大小取决于实现,但可能低至 256)。
您可以在 SetObjectArrayElement(…, jPeopleCount)
之后的创建它的循环中删除对 jPeopleCount 的本地引用。另一方面,所有这些本地引用将在 JNI 函数返回 obj->jPeopleCountArray 后自动释放。
同样,删除对 obj->jPeopleCountArray 元素的局部引用的循环是多余的。在使用 GetObjectArrayElement() 创建这些之前,不存在要处理的本地引用。
这演示了局部引用和全局引用之间的行为差异。您不需要为 jobjectArray 的每个元素创建全局引用。但是,如果您将 jPeopleCount 对象存储在 C++ 集合(例如数组)中,则每个对象都需要全局引用。在这种情况下,清理代码将遍历集合并释放这些全局引用,类似于您的代码。
关于jobjectarray 返回方法的 C++ NDK 库内存管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51221738/
在我的函数中,我试图获取已通过 JNI 传递给 C++ 类的字符串数组的大小,但我一直收到错误:“jobjectarray has not been declared”。这是我的 C++: int t
我有一个具有以下 JNI 方法的方法 JNIEXPORT void JNICALL Java_com_android_Coordinates_Updates ( JNIEnv * env, jobje
我有一个 Java 函数,它将接收可变数量的参数,并且在 JNI 中我接收 jobjectArray 中的所有参数。现在我的问题是:如何以原始形式返回参数(它们可以是字符串、 double 组、整数.
我是第一次使用 JNI。我有这个问题:在我的java代码中,有一个对象具有另一个对象(由我定义)的数组作为字段。现在,我需要从 native 代码设置此对象数组字段。我该怎么办? 提前谢谢您! :)
//***** 新问题。 ***** 当将结构传递给线程时,下面存在内存泄漏。不明白为什么,因为如果在主线程中直接调用线程内的代码不会泄漏内存。 class PeopleCounting{ //
我有 jobject 并且它里面有 jobjectArray,我正在使用 GetObjectField 获取 jobjectArray 然后转换它,但它不起作用任何人都可以帮忙吗? jfieldID
如何通过 jni 正确构造和传递不同对象的数组?我似乎无法将 jint 转换为 jobject。我原来的功能是: extern "C" JNIEXPORT jint ... Func(...) {
我正在使用 JNI 从 java 传递一个 jobjectarray(实际上是一个 byte[][])。 我想将其转换为 uint8_t* 或 vector (最好是后者)形式的可用“字节数组”,以便
我在使用 C++ 的 JNI 中工作,我创建了一个方法,其中一系列参数作为 jobjectarray 传递到我的 native 方法。我想使用这些参数在 JNI 中调用构造函数。但是,NewObjec
所以我决定将dll导入到我的java代码中。 它的作用是计算邻居矩阵。问题是我不知道如何将矩阵作为 jobobjectArray 返回。 JNIEXPORT jobjectArray JNICALL
请原谅我,因为我是 c++ jni 环境的新手 我正在尝试通过 JNI 桥将 String[] 数组从 Java 传递到 C++,同时遵循我在此处找到的提供此代码段的提示: void MyJNIFun
如果我尝试从 JNI 将 jstrings 传递给 jobjectArray 中的 Java,我就会出错。我对此进行了多次研究,它应该有效。但是我的签名 [Ljava/lang/String 不起作用
这个问题在这里已经有了答案: How to return an array from JNI to Java? (4 个答案) 关闭 7 年前。 我想在 c 中创建一个新数组,将原始数组加倍。这是我
我想使用 JNI 将字符串数组从 C 返回到 Java。我发现我可以这样使用 NewObjectArray(): JNIEXPORT jobjectArray JNICALL Java_Array_i
我想通过 JNI 将字符串数组从 C++ 传递给 Java,意味着将 String[] 返回给 java。 当我在 C++ 中打印 char* 时是正确的,但是当我在 Java 中打印 String
我正在开发一个调用 native dll 库的 Java 应用程序。我调用的 c++ 方法的代码: JNIEXPORT jobjectArray JNICALL Java_Surf_TopSurfWr
我使用以下代码来处理 Android 和 JNI 中的 JNI 数组。 但是我发现返回“jobjectArray”无法在 API 21/22 (Android 5.0) 上完成,但可以在 API 19
我是一名优秀的程序员,十分优秀!