I am a beginner in JNI programming. I am creating a HashMap<String, ArrayList<Integer>> in Java and passing it to JNI using the following code block:
#include <jni.h> // JNI header provided by JDK
#include <iostream> // C++ standard IO header
#include "HelloJNI.h" // Generated
#include <string>
#include <map>
#include <vector>
using namespace std;
// Implementation of the native method sayHello()
JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *env, jobject thisObj, jstring nameObj, jobject hashMap) {
std::map<std::string, vector<int>> mapOut;
// Get the Map's entry Set.
jclass mapClass = env->FindClass("java/util/Map");
if (mapClass == NULL) {
return;
}
jmethodID entrySet = env->GetMethodID(mapClass, "entrySet", "()Ljava/util/Set;");
if (entrySet == NULL) {
return;
}
jobject set = env->CallObjectMethod(hashMap, entrySet);
if (set == NULL) {
return;
}
// Obtain an iterator over the Set
jclass setClass = env->FindClass("java/util/Set");
if (setClass == NULL) {
return;
}
jmethodID iterator =
env->GetMethodID(setClass, "iterator", "()Ljava/util/Iterator;");
if (iterator == NULL) {
return;
}
jobject iter = env->CallObjectMethod(set, iterator);
if (iter == NULL) {
return;
}
// Get the Iterator method IDs
jclass iteratorClass = env->FindClass("java/util/Iterator");
if (iteratorClass == NULL) {
return;
}
jmethodID hasNext = env->GetMethodID(iteratorClass, "hasNext", "()Z");
if (hasNext == NULL) {
return;
}
jmethodID next =
env->GetMethodID(iteratorClass, "next", "()Ljava/lang/Object;");
if (next == NULL) {
return;
}
// Get the Entry class method IDs
jclass entryClass = env->FindClass("java/util/Map$Entry");
if (entryClass == NULL) {
return;
}
jmethodID getKey =
env->GetMethodID(entryClass, "getKey", "()Ljava/lang/Object;");
if (getKey == NULL) {
return;
}
jmethodID getValue =
env->GetMethodID(entryClass, "getValue", "()Ljava/lang/Object;");
if (getValue == NULL) {
return;
}
// Iterate over the entry Set
while (env->CallBooleanMethod(iter, hasNext)) {
jobject entry = env->CallObjectMethod(iter, next);
// retrieve key
jstring key = (jstring) env->CallObjectMethod(entry, getKey);
const char* keyStr = env->GetStringUTFChars(key, NULL);
if (!keyStr) { // Out of memory
return;
}
const char *keyobj = env->GetStringUTFChars(key, NULL);
// retrieve value
jobject jList = (jobject) env->CallObjectMethod(entry, getValue);
// retrieve the java.util.List interface class
jclass cList = env->FindClass("java/util/List");
// retrieve the size and the get method
jmethodID mSize = env->GetMethodID(cList, "size", "()I");
jmethodID mGet = env->GetMethodID(cList, "get", "(I)Ljava/lang/Object;");
if(mSize == NULL || mGet == NULL)
return;
// get the size of the list
jint size = env->CallIntMethod(jList, mSize);
// walk through and fill the vector
for(jint i=0;i<size;i++) {
jint intObj = (jint)env->CallIntMethod(jList, mGet, i);
mapOut[std::string(keyStr)].push_back(int(intObj));
//env->ReleaseStringUTFChars(intObj);
}
env->DeleteLocalRef(entry);
env->ReleaseStringUTFChars(key, keyStr);
env->DeleteLocalRef(key);
}
for(map<string, vector<int>>::iterator ii=mapOut.begin(); ii!=mapOut.end(); ++ii){
cout << (*ii).first << ": ";
vector <int> inVect = (*ii).second;
for (unsigned j=0; j<inVect.size(); j++){
cout << inVect[j] << " ";
}
cout << endl;
}
const char *name = env->GetStringUTFChars(nameObj, NULL);
cout << "Hello " << name << " from C++!" << endl;
return;
}
The output of the code is:
Canada: 2311168 2311176 2311184
England: 2311272 2311280 2311288 2311296
Pakistan: 2311224 2311232
Hello John from C++!
[{Canada=[22, 66, 99], Pakistan=[34, 6], England=[4, 20, 100, 55]}]
The hashmap in java prints successfully. However I am unable to retrieve Integer ArrayList values in JNI.