天天看點

C/C++啟動JVM

C/C++啟動JVM

  • ​​測試環境​​
  • ​​目錄結構​​
  • ​​需要的資源檔案路徑​​
  • jni.h
  • jni_md.h
  • jre
  • ​​代碼​​
  • ​​項目下載下傳​​

測試環境

系統:windwos 10
架構:x86_64
開發工具:Visual Studio 2019
java:1.8
      

目錄結構

C/C++啟動JVM

需要的資源檔案路徑

jni.h 頭檔案在  jdk/include/jin.h
jni_md.h 頭檔案在 jdk/include/win32/jni_md.h

jre 即java運作環境jvm在 jdk/jre
      

C/C++啟動JVM

C/C++啟動JVM

C/C++啟動JVM

代碼

#include "windows.h"
#include "iostream"
#include <tchar.h>
#include "jni.h"
#include <libloaderapi.h>

using namespace std;

typedef jint(JNICALL* JNICREATEPROC)(JavaVM**, void**, void*);

bool startJVM();

int _tmain(int argc, _TCHAR* argv[])
{
  cout << "Application run." << endl;
  startJVM();
  return 0;
}

//啟動java虛拟機
bool startJVM() {
  int pause;
  //擷取jvm動态庫的路徑
  TCHAR* jvmPath = _T(".\\jre\\bin\\server\\jvm.dll");

  //java虛拟機啟動時接收的參數,每個參數單獨一項
  int nOptionCount = 2;
  JavaVMOption vmOption[2];
  //設定JVM最大允許配置設定的堆記憶體,按需配置設定
  vmOption[0].optionString = "-Xmx1024M";
  //設定classpath
  vmOption[1].optionString = "-Djava.class.path=./Test.jar";

  JavaVMInitArgs vmInitArgs;
  vmInitArgs.version = JNI_VERSION_1_8;
  vmInitArgs.options = vmOption;
  vmInitArgs.nOptions = nOptionCount;
  //忽略無法識别jvm的情況
  vmInitArgs.ignoreUnrecognized = JNI_TRUE;

  //設定啟動類,注意分隔符為"/"
  const char startClass[] = "test/Test";
  //啟動方法,一般是main函數,當然可以設定成其他函數
  const char startMethod[] = "main";

  //加載JVM,注意需要傳入的字元串為LPCWSTR,指向一個常量Unicode字元串的32位指針,相當于const wchar_t*
  HINSTANCE jvmDLL = LoadLibrary(jvmPath);
  if (jvmDLL == NULL) {
    cout << "加載JVM動态庫錯誤" << endl;
    return false;
  }

  //初始化jvm實體位址
  JNICREATEPROC jvmProcAddress = (JNICREATEPROC)GetProcAddress(jvmDLL, "JNI_CreateJavaVM");
  if (jvmDLL == NULL) {
    FreeLibrary(jvmDLL);
    cout << "加載JVM動态庫錯誤" << endl;
    return false;
  }

  //建立JVM
  JNIEnv* env;
  JavaVM* jvm;
  jint jvmProc = (jvmProcAddress)(&jvm, (void**)&env, &vmInitArgs);
  if (jvmProc < 0 || jvm == NULL || env == NULL) {
    FreeLibrary(jvmDLL);
    cout << "建立JVM錯誤" << endl;
    return false;
  }

  //加載啟動類
  jclass mainclass = env->FindClass(startClass);
  if (env->ExceptionCheck() == JNI_TRUE || mainclass == NULL) {
    env->ExceptionDescribe();
    env->ExceptionClear();
    FreeLibrary(jvmDLL);
    cout << "加載啟動類失敗" << endl;
    return false;
  }

  //加載啟動方法
  jmethodID methedID = env->GetStaticMethodID(mainclass, startMethod, "([Ljava/lang/String;)V");
  if (env->ExceptionCheck() == JNI_TRUE || methedID == NULL) {
    env->ExceptionDescribe();
    env->ExceptionClear();
    FreeLibrary(jvmDLL);
    cout << "加載啟動方法失敗" << endl;
    cin >> pause;
    return false;
  }

  cout << "開始執行" << endl;
  env->CallStaticVoidMethod(mainclass, methedID, NULL);
  cout << "執行結束" << endl;

  //jvm釋放
  jvm->DestroyJavaVM();
  return true;
}
      

項目下載下傳