I'm trying to pass Mat
object to Java from C++ using JNI. I've looked inside the source code of OpenCV Java dll, and I'm using exact same code that OpenCV uses. When I want to release a Mat
object from Java, which is created by OpenCV Java API it works fine, but when I want to release a Mat
object that I've created using the same code my applications crashes.
I'm posting the codes that I'm using. I would be very appreciated if anybody has an idea. Thanks in advance.
[EDIT]
Also I would like to add one more remark, if you look at code blocks 3 and 4 function definitons in Java and C++ sides have same function names, readImage0, but in 1 and 2 in C++ side function name has an extra 1 on it's name, imread_11 and imread_1, how does those two get linked? Maybe there is an extra layer that I'm not aware of.
[/EDIT]
[EDIT2]
Running on Windows 7, VC11, tried both with OpenCV 2.4.5 and 2.4.8
[/EDIT2]
1. This is the C++ code to pass Mat
object in OpenCV source:
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. This is the Java code in OpenCV source:
public static Mat imread(String filename)
{
Mat retVal = new Mat(imread_1(filename));
return retVal;
}
private static native long imread_1(String filename);
3. This is my code:
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. This is my Java code:
public static Mat readImage(String imagePath)
{
Mat retVal = new Mat(readImage0(imagePath));
return retVal;
}
private static native long readImage0(String imagePath);
5. This is how I run the code:
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. This is what is written in 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. This is what is written in crash report:
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