技术说明:
- 这里的代码,通过加载libjvm然后找到产生函数。也有的代码直接调用(编译时需要链接)。
- 没有处理参数。
- MAC编译时需要链接 -framework CoreFoundation
Xcode设置编译链接-framework CoreFoundation_柳鲲鹏的博客-CSDN博客
- 根据自己的环境,修改USER_HOME_PATH/JRE_PATH/JAR_FILE_PATH/JAVA_MAIN_CLASS
- 代码如此整齐是六石编程学的要求,阁下应该学习并应用之。
此源码在各系统上都可以运行。WINDOWS上字串处理要特别注意。
#include <stdio.h> #include <stdlib.h> #include <dlfcn.h> #include <pthread.h> #include <jni.h> #ifdef __APPLE__ #define _DARWIN_BETTER_REALPATH #include <mach-o/dyld.h> #include <CoreServices/CoreServices.h> static void dummyCallback(void * info) {}; #endif #ifdef _WINDOWS #define LIB_SUFFIX "dll" #elif __APPLE__ #define LIB_SUFFIX "dylib" #else #define LIB_SUFFIX "so" #endif #ifdef _WINDOWS #define LIB_OPEN LoadLibrary #define LIB_CLOSE FreeLibrary #define LIB_METHOD GetProcAddress #else #define LIB_OPEN dlopen #define LIB_CLOSE dlclose #define LIB_METHOD dlsym #endif #define BUFFER_SIZE 256 #define USER_HOME_PATH "/Users/tsit" #define JRE_PATH USER_HOME_PATH "/tsjdk8-macosx/jre" #define LIB_JVM_PATH JRE_PATH "/lib/server/libjvm." LIB_SUFFIX #define JAR_FILE_PATH USER_HOME_PATH "/Develop/tsoffice.jar" #define JAVA_MAIN_CLASS "com/taishan/Office" #define JNI_CREATE_JNI "JNI_CreateJavaVM" /** 从libjvm中找到的函数,产生虚拟机。 */ typedef int (*CreateJavaVM_t)(JavaVM **ppJvm, void **ppEnv, void *pArgs); static void* g_pLibHandler = NULL; static JavaVM* g_pJvm = NULL; static JNIEnv* g_pJniEnv = NULL; static jclass g_jMainClass = NULL; static jmethodID g_jMainMethod = NULL; /** 从后向前 */ static void release_for_exit() { g_jMainMethod = NULL; g_jMainClass = NULL; if (g_pJniEnv != NULL) { g_pJniEnv->ExceptionDescribe(); g_pJniEnv->ExceptionClear(); g_pJniEnv = NULL; } if (g_pJvm != NULL) { g_pJvm->DestroyJavaVM(); g_pJvm = NULL; } if (g_pLibHandler != NULL) { LIB_CLOSE(g_pLibHandler); g_pLibHandler = NULL; } } static void load_jvm(char* pHomePath, JNIEnv **ppEnv, JavaVM **ppJvm) { char pJvmPath[BUFFER_SIZE] = {0}; strcpy(pJvmPath, LIB_JVM_PATH); g_pLibHandler = LIB_OPEN(pJvmPath, RTLD_NOW | RTLD_GLOBAL); if (g_pLibHandler == NULL) { return; } JavaVMOption options[10]; int counter = 0; options[counter++].optionString = (char*)"-XX:+UseG1GC"; options[counter++].optionString = (char*)"-XX:-UseAdaptiveSizePolicy"; options[counter++].optionString = (char*)"-XX:-OmitStackTraceInFastThrow"; options[counter++].optionString = (char*)"-Xmn512m"; options[counter++].optionString = (char*)"-Xmx2048m"; options[counter++].optionString = (char*)"-Djava.library.path=natives"; memset(pJvmPath, 0, BUFFER_SIZE); sprintf(pJvmPath, "-Djava.class.path=%s", JAR_FILE_PATH); options[counter++].optionString = (char*)strdup(pJvmPath); JavaVMInitArgs vm_args; memset(&vm_args, 0, sizeof(vm_args)); vm_args.version = JNI_VERSION_1_8; vm_args.nOptions = counter++; vm_args.options = options; vm_args.ignoreUnrecognized = JNI_TRUE; CreateJavaVM_t pCreateJvmFunction = (CreateJavaVM_t)LIB_METHOD(g_pLibHandler, JNI_CREATE_JNI); if (pCreateJvmFunction == NULL) { return; } int retCode = pCreateJvmFunction(ppJvm, (void**)ppEnv, &vm_args); if (retCode != 0 || *ppJvm == NULL || *ppEnv == NULL) { *ppJvm = NULL; *ppEnv = NULL; } } static void run_java_class() { if (g_pJniEnv == NULL) { return; } g_jMainClass = g_pJniEnv->FindClass(JAVA_MAIN_CLASS); if (g_pJniEnv->ExceptionCheck() == JNI_TRUE || g_jMainClass == NULL ) { return; } g_jMainMethod = g_pJniEnv->GetStaticMethodID(g_jMainClass, "main", "([Ljava/lang/String;)V"); if (g_pJniEnv->ExceptionCheck() == JNI_TRUE || g_jMainMethod == NULL) { return; } g_pJniEnv->CallStaticVoidMethod(g_jMainClass, g_jMainMethod, NULL); } void* thread_function(void* pData) { char pHomePath[512] = {0}; load_jvm(pHomePath, &g_pJniEnv, &g_pJvm); run_java_class(); return NULL; } int main(const int argc, const char** argv) { #ifdef __APPLE__ //如此奇怪的代码是吾同事搞定的。不这样就不对。 pthread_t tid; pthread_create(&tid, NULL, thread_function, NULL); CFRunLoopSourceContext sourceContext = { .version = 0, .info = NULL, .retain = NULL, .release = NULL, .copyDescription = NULL, .equal = NULL, .hash = NULL, .schedule = NULL, .cancel = NULL, .perform = &dummyCallback}; CFRunLoopRef loopRef = CFRunLoopGetCurrent(); CFRunLoopSourceRef sourceRef = CFRunLoopSourceCreate(NULL, 0, &sourceContext); CFRunLoopAddSource(loopRef, sourceRef, kCFRunLoopCommonModes); CFRunLoopRun(); CFRelease(sourceRef); #else thread_function(NULL); #endif release_for_exit(); return 0; }