歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> 從 C/C++ 程序調用 Java 代碼

從 C/C++ 程序調用 Java 代碼

日期:2017/3/1 11:09:30   编辑:Linux編程

JNI允許您從本機代碼內調用 Java 類方法。

要做到這一點,通常必須使用 Invocation API 在本機代碼內創建和初始化一個 JVM。

下列是您可能決定從 C/C++ 代碼調用Java 代碼的典型情況:

1.希望實現的這部分代碼是平台無關的,它將用於跨多種平台使用的功能。

2.需要在本機應用程序中訪問用 Java 語言編寫的代碼或代碼庫。

3.希望從本機代碼利用標准 Java 類庫。

從C/C++ 程序調用 Java 代碼的四個步驟:

1.編寫 Java 代碼。

這個步驟包含編寫一個或多個 Java 類,這些類實現(或調用其它方法實現)您想要訪問的功能。

2.編譯 Java 代碼。

在能夠使用這些 Java 類之前,必須成功地將它們編譯成字節碼。

3.編寫 C/C++ 代碼。

這個代碼將創建和實例化 JVM,並調用正確的 Java 方法。

4.運行本機 C/C++ 應用程序。

將運行應用程序以查看它是否正常工作。我們還將討論一些用於處理常見錯誤的技巧。

步驟 1:編寫Java 代碼
我們從編寫一個或多個 Java 源代碼文件開始,這些文件將實現我們想要本機 C/C++ 代碼使用的功能。
下面顯示了一個 Java 代碼示例JNI_cCalljava_test.java:
  1. package test;
  2. public class JNI_cCalljava_test {
  3. public static int intMethod(int n) {
  4. return n*n;
  5. }
  6. public static boolean booleanMethod(boolean bool) {
  7. return !bool;
  8. }
  9. }

注:JNI_cCalljava_test.java 實現了兩個 static Java 方法:intMethod(intn) 和 booleanMethod(boolean bool)(分別在第 3 行和第 7 行)。static方法是一種不需要與對象實例關聯的類方法。調用 static方法要更容易些,因為不必實例化對象來調用它們。

步驟 2:編譯Java 代碼

接下來,我們將 Java 代碼編譯成字節碼。

完成這一步的方法之一是使用隨SDK 一起提供的Java 編譯器 javac。使用的命令是:

JNI_cCalljava_test.java

或者直接在eclipose中編寫保存即可

步驟 3:編寫 C/C++ 代碼

即使是在本機應用程序中運行,所有 Java 字節碼也必須在 JVM 中執行。

因此 C/C++ 應用程序必須包含用來創建和初始化 JVM 的調用。

為了方便我們,SDK 包含了作為共享庫文件(jvm.dll 或 jvm.so)的 JVM,這個庫文件可以嵌入到本機應用程序中。


讓我們先從浏覽一下 C 和 C++ 應用程序的整個代碼開始,然後對兩者進行比較。

帶有嵌入式 JVM的 C 應用程序:

  1. #include <jni.h>
  2. //jni.h文件包含在 C 代碼中所需要的 JNI 的所有類型和函數定義
  3. #ifdef _WIN32
  4. #define PATH_SEPARATOR ';'
  5. #else
  6. #define PATH_SEPARATOR ':'
  7. #endif
  8. //1.包括准備本機應用程序以處理 Java 代碼
  9. //2.將 JVM 嵌入本機應用程序
  10. //3.然後從該應用程序內找到並調用 Java 方法。
  11. int main()
  12. {
  13. /*
  14. 接下來,聲明所有希望在程序中使用的變量。
  15. JavaVMOption options[] 具有用於 JVM 的各種選項設置。
  16. 當聲明變量時,確保所聲明的JavaVMOption options[] 數組足夠大,以便能容納您希望使用的所有選項。
  17. 在本例中,我們使用的唯一選項就是類路徑選項。
  18. 因為在本示例中,我們所有的文件都在同一目錄中,所以將類路徑設置成當前目錄。
  19. 可以設置類路徑,使它指向任何您希望使用的目錄結構。*/
  20. JavaVMOption options[1];
  21. JNIEnv *env;
  22. JavaVM *jvm;
  23. JavaVMInitArgs vm_args;
  24. /*JNIEnv *env 表示 JNI 執行環境。
  25. JavaVM jvm 是指向 JVM 的指針,我們主要使用這個指針來創建、初始化和銷毀 JVM。
  26. JavaVMInitArgs vm_args 表示可以用來初始化 JVM 的各種 JVM 參數。*/
  27. long status;
  28. jclass cls;
  29. jmethodID mid;
  30. jint square;
  31. jboolean not;
  32. /*avaVMInitArgs 結構表示用於 JVM 的初始化參數。
  33. 在執行 Java 代碼之前,可以使用這些參數來定制運行時環境。
  34. 正如您所見,這些選項是一個參數,而 Java 版本是另一個參數。
  35. 按如下所示設置了這些參數:*/
  36. /*為 JVM 設置類路徑,以使它能找到所需要的 Java 類。
  37. 在這個特定示例中,因為 Sample2.class 和Sample2.exe 都位於同一目錄中,所以將類路徑設置成當前目錄。
  38. 我們用來為 Sample2.c 設置類路徑的代碼如下所示:*/
  39. options[0].optionString = "-Djava.class.path=.";
  40. memset(&vm_args, 0, sizeof(vm_args));
  41. vm_args.version = JNI_VERSION_1_2;
  42. vm_args.nOptions = 1;
  43. vm_args.options = options;
  44. /*創建 JVM
  45. 處理完所有設置之後,現在就准備創建 JVM 了。先從調用方法開始
  46. 如果成功,則這個方法返回零,否則,如果無法創建 JVM,則返回JNI_ERR。*/
  47. status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
  48. if (status != JNI_ERR)
  49. {
  50. /*
  51. 查找並裝入 Java 類
  52. 一旦創建了 JVM 之後,就可以准備開始在本機應用程序中運行 Java 代碼。
  53. 首先,需要使用FindClass() 函數查找並裝入 Java 類,如下所示:
  54. cls 變量存儲執行FindClass() 函數後的結果,如果找到該類,則 cls 變量表示該Java 類的句柄,
  55. 如果不能找到該類,則 cls 將為零。
  56. */
  57. cls = (*env)->FindClass(env, "test/JNI_cCalljava_test");
  58. printf("test1,cls=%d...\n",cls);
  59. if(cls !=0)
  60. {
  61. /*
  62. 查找 Java 方法
  63. 接下來,我們希望用 GetStaticMethodID() 函數在該類中查找某個方法。
  64. 我們希望查找方法 intMethod,它接收一個 int 參數並返回一個 int。
  65. 以下是查找 intMethod 的代碼:
  66. */
  67. mid = (*env)->GetStaticMethodID(env, cls, "intMethod", "(I)I");
  68. /*
  69. mid 變量存儲執行 GetStaticMethodID() 函數後的結果。
  70. 如果找到了該方法,則 mid 變量表示該方法的句柄。
  71. 如果不能找到該方法,則mid 將為零。
  72. */
  73. if(mid !=0)
  74. {
  75. /*CallStaticIntMethod() 方法接受 cls(表示類)、mid(表示方法)以及用於該方法一個或多個參數。
  76. 在本例中參數是 int 5。*/
  77. square = (*env)->CallStaticIntMethod(env, cls, mid, 5);
  78. printf("Result of intMethod: %d\n", square);
  79. }
  80. mid = (*env)->GetStaticMethodID(env, cls, "booleanMethod", "(Z)Z");
  81. if(mid !=0)
  82. {
  83. not = (*env)->CallStaticBooleanMethod(env, cls, mid, 1);
  84. printf("Result of booleanMethod: %d\n", not);
  85. }
  86. }
  87. (*jvm)->DestroyJavaVM(jvm);
  88. return 0;
  89. }
  90. else
  91. return -1;
  92. }
Copyright © Linux教程網 All Rights Reserved