Return jintArray from JNI

I am trying to return a jintArray from C ++ to Java, but the application seems to hang in a JNI call. I shared the issue with the creation and population of jintArray, although I am not getting any errors. Any help is appreciated.

Check the project to make sure everything works:

include "stdafx.h" include "windows.h" include <vector> include <iostream> include <jni.h> using namespace std; std::vector<jint> childWindows; BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam) { childWindows.push_back((jint) hwnd); return TRUE; } jint* getChildWindows(HWND hWnd) { childWindows.clear(); ::EnumChildWindows(hWnd, EnumChildProc, NULL); int len = static_cast<int>(childWindows.size()); jint values[100]; std::copy(childWindows.begin(), childWindows.end(), values); for (std::vector<jint>::const_iterator i = childWindows.begin(); i != childWindows.end(); ++i) { std::cout << (HWND)*i << ' '; } //env->SetIntArrayRegion(childeren, 0, len, values); return values; } int _tmain(int argc, _TCHAR* argv[]) { getChildWindows((HWND)1377258); std::cout << " | Windows count: " << childWindows.size() << " "; return 0; } 

Output:

<000 000 000 000 000 000 000 00050570 00060512 000C04E0 | Number of Windows: 10

Java Code:

  System.out.println("Get child windows"); System.out.println("Main handle: " + getHandle()); final int[] handles = getChildWindows(); System.out.println("Done getting childs"); 

Java output:

Running test child windows

Get child windows

Main handle: 525978

JNI Code:

 JNIEXPORT jintArray JNICALL Java_main_getChildWindows(JNIEnv *env, jclass c) { childWindows.clear(); ::EnumChildWindows(hWnd, EnumChildProc, NULL); int len = static_cast<int>(childWindows.size()); jintArray childeren = env->NewIntArray(len); jint values[100]; std::copy(childWindows.begin(), childWindows.end(), values); env->SetIntArrayRegion(childeren, (jsize)0, (jsize)len, values); //env->ReleaseIntArrayElements(childeren, values, 0); return childeren; } 
+6
source share
1 answer

You do not check for errors after JNI calls. This can lead to a situation where the code crashes not in the place where the error was, but in the next place where you call the JVM. When this happens, you will not get "errors" in any friendly sense. Your chance to get them is to check the return values โ€‹โ€‹and request a JVM for pending exceptions. (See below.)

In your case, for example, if

 jintArray childeren = env->NewIntArray(len) 

throws an exception (in Java in the JVM), your code will continue after this line in the native code, but the JVM will still hold that exception. The next time you call the JVM, which turns out to be the line that you defined where you set the values โ€‹โ€‹of the array, the code will crash. You need to explicitly clear the exception.

In any case, you should check the return values โ€‹โ€‹and check for exceptions. (See JNI Docs for ExceptionOccurred and ExceptionClear.) I would say that for some reason you were unable to get the allocated array. The reason why this happens is not clear to me from your code, but it will give you a specific place to start, that is, if you have an exception or you have a null link that will give you information about what went wrong. It will also potentially transfer your search to the location of the problem.

Good luck

+1
source

All Articles