gpt4 book ai didi

java - 无法在 Java 中释放 Mat 对象

转载 作者:可可西里 更新时间:2023-11-01 17:57:44 30 4
gpt4 key购买 nike

我正在尝试使用 JNIMat 对象从 C++ 传递给 Java。我查看了 OpenCV Java dll 的源代码,我使用的代码与 OpenCV 使用的代码完全相同。当我想从 Java 释放一个由 OpenCV Java API 创建的 Mat 对象时,它工作正常,但是当我想释放一个我创建的 Mat 对象时使用相同的代码我的应用程序崩溃了。

我正在发布我正在使用的代码。如果有人有想法,我将不胜感激。提前致谢。

[编辑]

此外,我还想再补充一点,如果您查看代码块 3 和 4,Java 和 C++ 端的函数定义具有相同的函数名称,readImage0,但在 C++ 中的 1 和 2 中side function name 的名称上有一个额外的 1,imread_11imread_1,这两者如何关联?也许还有一个我不知道的额外层。

[/EDIT]

[EDIT2]

在 Windows 7、VC11 上运行,尝试使用 OpenCV 2.4.5 和 2.4.8

[/EDIT2]

<强>1。这是在 OpenCV 源代码中传递 Mat 对象的 C++ 代码:

JNIEXPORT jlong JNICALL Java_org_opencv_highgui_Highgui_imread_11 (JNIEnv*, jclass, jstring);

JNIEXPORT jlong JNICALL Java_org_opencv_highgui_Highgui_imread_11
(JNIEnv* env, jclass , jstring filename)
{
static const char method_name[] = "highgui::imread_11()";
try {
LOGD("%s", method_name);
const char* utf_filename = env->GetStringUTFChars(filename, 0); std::string n_filename( utf_filename ? utf_filename : "" ); env->ReleaseStringUTFChars(filename, utf_filename);
Mat _retval_ = cv::imread( n_filename );
return (jlong) new Mat(_retval_);
} catch(const std::exception &e) {
throwJavaException(env, &e, method_name);
} catch (...) {
throwJavaException(env, 0, method_name);
}
return 0;
}

<强>2。这是 OpenCV 源代码中的 Java 代码:

public static Mat imread(String filename)
{
Mat retVal = new Mat(imread_1(filename));
return retVal;
}

private static native long imread_1(String filename);

<强>3。这是我的代码:

JNIEXPORT jlong JNICALL Java_tr_com_guney_opencvcpp2java_OpenCVCpp2Java_readImage0(JNIEnv *env, jclass, jstring imagePath)

JNIEXPORT jlong JNICALL Java_tr_com_guney_opencvcpp2java_OpenCVCpp2Java_readImage0(JNIEnv *env, jclass, jstring imagePath)
{
static const char method_name[] = "OpenCVCpp2Java::readImage0()";
try {
LOGD("%s", method_name);
const char* utf_filename = env->GetStringUTFChars(imagePath, 0); std::string n_filename( utf_filename ? utf_filename : "" ); env->ReleaseStringUTFChars(imagePath, utf_filename);
cv::Mat _retval_ = cv::imread( n_filename );
return (jlong) new cv::Mat(_retval_);
} catch(const std::exception &e) {
throwJavaException(env, &e, method_name);
} catch (...) {
throwJavaException(env, 0, method_name);
}
return 0;
}

<强>4。这是我的 Java 代码:

public static Mat readImage(String imagePath) 
{
Mat retVal = new Mat(readImage0(imagePath));
return retVal;
}

private static native long readImage0(String imagePath);

<强>5。这是我运行代码的方式:

Mat image = Highgui.imread("e:/image.png"); //this works fine
Highgui.imwrite("e:/imageJava.png", image); // this is to check if image is read correctly and works fine
image.release(); // this works fine
//system.gc(); // this also works fine

Mat image2 = OpenCVCpp2Java.readImage("e:/image.png"); //this works fine
Highgui.imwrite("e:/imageJava2.png", image2); // this is to check if image is read correctly and works fine
image2.release(); // this throws exception!
//system.gc(); // this causes application to crash!

6. Exception中是这样写的:

Exception in thread "main" java.lang.Exception: Unknown exception in JNI code {Mat::n_1release()}
at org.opencv.core.Mat.n_release(Native Method)
at org.opencv.core.Mat.release(Mat.java:1875)

7.这是崩溃报告中写的:

Stack: [0x28880000,0x288d0000],  sp=0x288cf620,  free space=317k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [ntdll.dll+0x2e3be] RtlInitUnicodeString+0x196
C [ntdll.dll+0x2e023] RtlFreeHeap+0x7e
C [kernel32.dll+0x114ad] HeapFree+0x14
C [opencv_java245.dll+0x48e877] Java_org_opencv_contrib_Contrib_chamerMatching_11+0x429a47
C [opencv_java245.dll+0x904f3] Java_org_opencv_contrib_Contrib_chamerMatching_11+0x2b6c3
C [opencv_java245.dll+0x6516a] Java_org_opencv_contrib_Contrib_chamerMatching_11+0x33a
j org.opencv.core.Mat.n_delete(J)V+0
j org.opencv.core.Mat.finalize()V+4
v ~StubRoutines::call_stub
V [jvm.dll+0xfb88b]
V [jvm.dll+0x18d551]
V [jvm.dll+0xfb90d]
V [jvm.dll+0x96301]
V [jvm.dll+0x990c9]
C [java.dll+0x2100] Java_java_lang_ref_Finalizer_invokeFinalizeMethod+0x39
j java.lang.ref.Finalizer.runFinalizer()V+45
j java.lang.ref.Finalizer.access$100(Ljava/lang/ref/Finalizer;)V+1
j java.lang.ref.Finalizer$FinalizerThread.run()V+24
v ~StubRoutines::call_stub
V [jvm.dll+0xfb88b]
V [jvm.dll+0x18d551]
V [jvm.dll+0xfba31]
V [jvm.dll+0xfba8b]
V [jvm.dll+0xb5e89]
V [jvm.dll+0x119b74]
V [jvm.dll+0x14217c]
C [msvcr71.dll+0x9565] endthreadex+0xa0
C [kernel32.dll+0x1336a] BaseThreadInitThunk+0x12
C [ntdll.dll+0x39f72] RtlInitializeExceptionChain+0x63
C [ntdll.dll+0x39f45] RtlInitializeExceptionChain+0x36

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j org.opencv.core.Mat.n_delete(J)V+0
j org.opencv.core.Mat.finalize()V+4
v ~StubRoutines::call_stub
j java.lang.ref.Finalizer.invokeFinalizeMethod(Ljava/lang/Object;)V+0
j java.lang.ref.Finalizer.runFinalizer()V+45
j java.lang.ref.Finalizer.access$100(Ljava/lang/ref/Finalizer;)V+1
j java.lang.ref.Finalizer$FinalizerThread.run()V+24
v ~StubRoutines::call_stub

最佳答案

我已经弄清楚问题出在哪里了。我认为这有点复杂,至少对我来说是这样。

问题是我使用的是 opencv_java248.dll,它随 OpenCV 一起分发并且已经编译。 opencv_java248.dll 是静态构建的,这意味着它在编译后不需要任何 OpenCV dll(opencv_core248.dll 等)。我已经创建了自己的 dll opencvcpp2java.dll,它也是静态构建的,因此在运行时不需要任何 dll。

发生崩溃后,我开始思考是什么导致了这个问题。然后我意识到内存分配和释放是在完全不同的 dll 上完成的。我正在使用 opencvcpp2java.dll 分配内存并期望 opencv_java248.dll 释放它。当它试图释放它时,程序崩溃了。另一方面,当我使用 opencv_java248.dll 进行分配和释放时,没有问题。所以,作为一种直觉,我认为分配和释放应该在同一个 dll 上完成。

根据这种直觉,我自己编译了 opencv_java248.dll(顺便说一句,为此您需要编译所有 OpenCV dll,当您使用 CMake 时它是小菜一碟)并使其依赖于其他 OpenCV dll 并重新编译 opencvcpp2java。 dll 并使其依赖于 OpenCV dll。 所以当我想使用 opencvcpp2java.dll 分配内存时它使用 OpenCV dll 分配内存(更具体地说是 opencv_core248.dll),当我想使用 opencv_java248.dll 释放内存时它使用与它创建时相同的 dll 释放内存

我不是 100% 确定这是正确的解决方案,但它对我有用。

关于java - 无法在 Java 中释放 Mat 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22555174/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com