Reputation: 1
I have problem to get path of actual jar file in cpp(native JNI), could someone give me some clue? My CodeSource jobject is NULL
jclass thisObj = env->FindClass("Main");
jmethodID firstMid = env->GetMethodID(thisObj, "<init>", "()V");
jobject firstObjClass = env->NewObject(thisObj, firstMid);
jclass main = env->GetObjectClass(firstObjClass);
jmethodID mid = env->GetMethodID(main, "getClass", "()Ljava/lang/Class;");
if (mid == 0) return;
jobject objClass = env->CallObjectMethod(thisObj, mid);
jclass clsclass = env->GetObjectClass(objClass);
jmethodID midPD = env->GetMethodID(clsclass, "getProtectionDomain", "()Ljava/security/ProtectionDomain;");
if (midPD == 0)return;
jobject objPD = env->CallObjectMethod(objClass, midPD);
jclass clsPD = env->GetObjectClass(objPD);
jmethodID midCS = env->GetMethodID(clsPD, "getCodeSource", "()Ljava/security/CodeSource;");
jobject objCS = env->CallObjectMethod(objPD, midCS);
jclass clscs = env->GetObjectClass(objCS);
jmethodID locMethod = env->GetMethodID(clscs, "getLocation", "()Ljava/net/URL");
jobject locObj = env->CallObjectMethod(objCS, locMethod);
jclass locClass = env->GetObjectClass(locObj);
jmethodID pathMethod = env->GetMethodID(locClass, "getPath", "()Ljava/lang/String");
jobject path = env->CallObjectMethod(locObj, pathMethod);
cout << path << endl;
return;
}
Upvotes: 0
Views: 324
Reputation: 13375
I'd have definitely added some helper method inside Java class. But you can do it from JNI as well.
// Now, let's get it hard way. Let's make a hell lot of JNI based calls
// Note! I don't care for error handling - but you should check whether
// each call produced something sensible or not
jmethodID method_Main_init = (*env)->GetMethodID(env, cls_Main, "<init>", "()V");
jobject obj_Main = (*env)->NewObject(env, cls_Main, method_Main_init);
jmethodID method_getClass = (*env)->GetMethodID(env, cls_Main, "getClass", "()Ljava/lang/Class;");
jobject obj_Class = (*env)->CallObjectMethod(env, obj_Main, method_getClass);
jclass cls_Class = (*env)->GetObjectClass(env, obj_Class);
jmethodID method_getProtectionDomain = (*env)->GetMethodID(env, cls_Class, "getProtectionDomain", "()Ljava/security/ProtectionDomain;");
jobject obj_ProtectionDomain = (*env)->CallObjectMethod(env, obj_Class, method_getProtectionDomain);
jclass cls_ProtectionDomain = (*env)->GetObjectClass(env, obj_ProtectionDomain);
jmethodID method_getCodeSource = (*env)->GetMethodID(env, cls_ProtectionDomain, "getCodeSource", "()Ljava/security/CodeSource;");
jobject obj_CodeSource = (*env)->CallObjectMethod(env, obj_ProtectionDomain, method_getCodeSource);
jclass cls_CodeSource = (*env)->GetObjectClass(env, obj_CodeSource);
jmethodID method_getLocation = (*env)->GetMethodID(env, cls_CodeSource, "getLocation", "()Ljava/net/URL;");
jobject obj_URL = (*env)->CallObjectMethod(env, obj_CodeSource, method_getLocation);
jclass cls_URL = (*env)->GetObjectClass(env, obj_URL);
jmethodID method_toURI = (*env)->GetMethodID(env, cls_URL, "toURI", "()Ljava/net/URI;");
jobject obj_URI = (*env)->CallObjectMethod(env, obj_URL, method_toURI);
jclass cls_File = (*env)->FindClass (env, "java/io/File");
jmethodID method_File_init = (*env)->GetMethodID(env, cls_File, "<init>", "(Ljava/net/URI;)V");
jobject obj_File = (*env)->NewObject(env, cls_File, method_File_init, obj_URI);
jmethodID method_getPath = (*env)->GetMethodID(env, cls_File, "getPath", "()Ljava/lang/String;");
jobject obj_String = (*env)->CallObjectMethod(env, obj_File, method_getPath);
// Finally, we have path, all we have to do is to "cast" it to char *
// and print it
const char *c_str;
c_str = (*env)->GetStringUTFChars(env, obj_String, NULL);
if(c_str != NULL) {
printf("Path from JNI: %s\n", c_str);
} else {
printf("Something went wrong :(");
}
For a sample code, take a look here: https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo050
Why does it fail
It fails, because there are mixtures of jclass
and jobject
here and there (also, missing semicolons). This is why my code is not only well formatted, it's also working ;) If you want to learn what was broken in your code, feel free to compare your version with one below.
jclass thisObj = (*env)->FindClass(env, "Main");
jmethodID firstMid = (*env)->GetMethodID(env, thisObj, "<init>", "()V");
jobject firstObjClass = (*env)->NewObject(env, thisObj, firstMid);
jclass main = (*env)->GetObjectClass(env, firstObjClass);
jmethodID mid = (*env)->GetMethodID(env, main, "getClass", "()Ljava/lang/Class;");
jobject objClass = (*env)->CallObjectMethod(env, firstObjClass, mid);
jclass clsclass = (*env)->GetObjectClass(env, objClass);
jmethodID midPD = (*env)->GetMethodID(env, clsclass, "getProtectionDomain", "()Ljava/security/ProtectionDomain;");
jobject objPD = (*env)->CallObjectMethod(env, objClass, midPD);
jclass clsPD = (*env)->GetObjectClass(env, objPD);
jmethodID midCS = (*env)->GetMethodID(env, clsPD, "getCodeSource", "()Ljava/security/CodeSource;");
jobject objCS = (*env)->CallObjectMethod(env,objPD, midCS);
jclass clscs = (*env)->GetObjectClass(env, objCS);
jmethodID locMethod = (*env)->GetMethodID(env, clscs, "getLocation", "()Ljava/net/URL;");
jobject locObj = (*env)->CallObjectMethod(env, objCS, locMethod);
jclass locClass = (*env)->GetObjectClass(env, locObj);
jmethodID pathMethod = (*env)->GetMethodID(env, locClass, "getPath", "()Ljava/lang/String;");
jobject path = (*env)->CallObjectMethod(env, locObj, pathMethod);
Upvotes: 1