JNI如何从cpp获取jar位置

时间:2019-07-30 14:55:48

标签: java c++ java-native-interface native jna

我在cpp(本机JNI)中获取实际jar文件的路径时遇到问题,有人可以给我一些提示吗? 我的CodeSource工作项目为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;
}

1 个答案:

答案 0 :(得分:1)

我肯定会在Java类中添加一些辅助方法。但是您也可以从JNI做到这一点。

  // 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 :(");
  }

有关示例代码,请在此处查看:https://github.com/mkowsiak/jnicookbook/tree/master/recipeNo050

为什么会失败

它失败了,因为到处都是jclassjobject的混合体(也缺少分号)。这就是为什么我的代码不仅格式正确,而且还能正常工作的原因;)如果您想了解代码中的损坏之处,请随时将您的版本与以下代码进行比较。

    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);