JNI usa C para cargar JDK para generar una máquina virtual JVM y ejecutar la función principal de la clase JAVA (MACOS/LINUX/WINDOWS)

Descripción técnica:

  • El código aquí se genera cargando libjvm y luego encontrando la función. También se llama directamente a algún código (requiere vinculación al compilar).
  • Sin parámetros de procesamiento.
  • La compilación MAC requiere vinculación -framework CoreFoundation

Enlace de compilación de configuración de Xcode: marco CoreFoundation: blog de Liu Kunpeng: blog de CSDN

  • Modifique USER_HOME_PATH/JRE_PATH/JAR_FILE_PATH/JAVA_MAIN_CLASS según su propio entorno
  • El código es tan limpio y ordenado que es el requisito de la programación de Six Stones, debe aprenderlo y aplicarlo.

Este código fuente funciona en todos los sistemas. Se debe prestar especial atención al procesamiento de cadenas en 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;
}

Supongo que te gusta

Origin blog.csdn.net/quantum7/article/details/123683545
Recomendado
Clasificación