NoEasy
NoEasy

Reputation: 1

JNI How to get jar location from cpp

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

Answers (1)

Oo.oO
Oo.oO

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

Related Questions