JNI用C加载JDK产生JVM虚拟机,并运行JAVA类main函数(MACOS/LINUX/WINDOWS)

简介: JNI用C加载JDK产生JVM虚拟机,并运行JAVA类main函数(MACOS/LINUX/WINDOWS)

技术说明:


这里的代码,通过加载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;
}

目录
相关文章
|
2月前
|
Java Linux
Linux复制安装 jdk 环境
Linux复制安装 jdk 环境
50 3
|
1月前
|
Java
Java常见JVM虚拟机指令(47个)
Java常见JVM虚拟机指令(47个)
43 3
Java常见JVM虚拟机指令(47个)
|
29天前
|
消息中间件 Java 中间件
在Linux中,什么是中间件?什么是jdk?
在Linux中,什么是中间件?什么是jdk?
|
1月前
|
关系型数据库 Java MySQL
Linux安装JDK1.8 & tomcat & MariaDB(MySQL删减版)
本教程提供了在Linux环境下安装JDK1.8、Tomcat和MariaDB的详细步骤。这三个组件的组合为Java Web开发和部署提供了一个强大的基础。通过遵循这些简单的指导步骤,您可以轻松建立起一个稳定、高效的开发和部署环境。希望这个指导对您的开发工作有所帮助。
86 8
|
28天前
|
Java 数据安全/隐私保护 Windows
【Azure Developer】使用Java代码启动Azure VM(虚拟机)
【Azure Developer】使用Java代码启动Azure VM(虚拟机)
|
29天前
|
存储 Java API
【Azure Developer】通过Azure提供的Azue Java JDK 查询虚拟机的CPU使用率和内存使用率
【Azure Developer】通过Azure提供的Azue Java JDK 查询虚拟机的CPU使用率和内存使用率
|
2月前
|
监控 Oracle Java
(一)JVM成神路之初识虚拟机 - 探寻Java虚拟机的前世今生之秘
JVM(Java Virtual Machine)Java虚拟机的概念大家都不陌生,Java之所以可以做到“一次编译,到处运行”的跨平台性,其根本原因就在于JVM。JVM是建立在操作系统(OS)之上的,Java虚拟机屏蔽了开发人员与操作系统的直接接触,我们在通过Java编写程序时,只需要负责编写Java代码即可,关于具体的执行则会由JVM加载字节码后翻译成机械指令交给OS执行。
|
1月前
|
Oracle Java 关系型数据库
简单记录在Linux上安装JDK环境的步骤,以及解决运行Java程序时出现Error Could not find or load main class XXX问题
本文记录了在Linux系统上安装JDK环境的步骤,并提供了解决运行Java程序时出现的"Error Could not find or load main class XXX"问题的方案,主要是通过重新配置和刷新JDK环境变量来解决。
66 0
|
2月前
|
监控 算法 Java
深入理解Java虚拟机:内存管理与性能优化
在Java的世界里,虚拟机(JVM)是幕后的守护者,它默默地支撑着每一个字节码的运行。本文将揭开JVM的神秘面纱,探讨其内存管理机制及如何通过调优提升应用性能。从堆内存的分配到垃圾回收的策略,再到实践中的性能监控与调优技巧,我们将一同走进JVM的内部世界,学习如何让我们的Java程序跑得更快、更稳。
|
存储 Linux Windows
linux运行的硬件基础
1、i386 的寄存器    80386作为80X86系列中的一员,必须保证向后兼容,也就是说,既要支持16位的处理器,也要支持32位的处理器。在8086中,所有的寄存器都是16位的,下面我们来看一下80386中寄存器有何变化: ·      把16位的通用寄存器、标志寄存器以及指令指针寄存器扩充为32位的寄存器 ·      段寄存器仍然为16位。
939 0