使用C++创建jvm虚拟机

JNI,全称Java Native Interface,我们一般使用它在Java中调用C++方法。实际上,如果我们愿意同样也可以在C++中调用Java方法。
这里我们使用到的技术叫做,The Invocation API

我们还是使用CMake来构建项目。

1. CMakeLists.txt的配置

cmake_minimum_required(VERSION 2.8)
project(Review)
set(BUILD_USE_64BITS on)
FIND_PACKAGE(JNI REQUIRED)
include_directories(${JNI_INCLUDE_DIRS})
ADD_EXECUTABLE(jvmLuncher main.cpp)
target_link_libraries(jvmLuncher ${JAVA_JVM_LIBRARY})

这里有几点要说明的地方:

  • set(BUILD_USE_64BITS on)为的是编译64位版本
  • FIND_PACKAGE(JNI REQUIRED)是让CMake自动去寻找Java相关的路径。
    这里可以自动找到的路径有:

    JNI_INCLUDE_DIRS = the include dirs to use
    JNI_LIBRARIES = the libraries to use
    JNI_FOUND = TRUE if JNI headers and libraries were found.
    JAVA_AWT_LIBRARY = the path to the jawt library
    JAVA_JVM_LIBRARY = the path to the jvm library
    JAVA_INCLUDE_PATH = the include path to jni.h
    JAVA_INCLUDE_PATH2 = the include path to jni_md.h
    JAVA_AWT_INCLUDE_PATH = the include path to jawt.h

  • target_link_libraries(jvmLuncher ${JAVA_JVM_LIBRARY})用于指定在jvmLuncher链接时,使用JAVA_JVM_LIBRARY库

    这里JAVA_JVM_LIBRARY指向的是jvm.lib。

    link_directories
    Specify directories in which the linker will look for libraries.
    link_directories(directory1 directory2 …)
    Specify the paths in which the linker should search for libraries. The command will apply only to targets created after it is called. Relative paths given to this command are interpreted as relative to the current source directory, see CMP0015.
    Note that this command is rarely necessary. Library locations returned by find_package() and find_library() are absolute paths. Pass these absolute library file paths directly to the target_link_libraries() command. CMake will ensure the linker finds them.

2. 代码

main.cpp
#include <stdio.h>
#include <stdlib.h>
#include <jni.h>

JavaVM *jvm;
JNIEnv *env;

void JVM_Init()
{
    JavaVMInitArgs vm_args;
    JavaVMOption options[1];

    vm_args.version = JNI_VERSION_1_6;
    vm_args.ignoreUnrecognized = false;
    vm_args.nOptions = 0;

    char classpath[1024] = "-Djava.class.path=";
    // char *env_classpath = getenv("CLASSPATH");

    // if (env_classpath) {
        // options[0].optionString = strcat(classpath, env_classpath);
        options[0].optionString = "-Djava.class.path=C:/Program Files/Java/jdk1.8.0_20";
        vm_args.nOptions++;
    // }

    if (vm_args.nOptions > 0) {
        vm_args.options = options;
    }

    // create jvm
    jint res = JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args);
    // delete options;
    if (res < 0) {
        printf("Create Java VM error, code = %d\n", res);
        exit(-1);
    }
    printf("Create Java VM successful!, code = %d\n", res);
}

void JVM_Destroy()
{
    jvm->DestroyJavaVM();
    env = NULL;
    jvm = NULL;
}

int main(){
    printf("Hello World!");
    JVM_Init();
}
简单说明: 想要创建jvm需要一些参数,这些参数存放在一个JavaVMInitArgs实例中。 JavaVMInitArgs需要包含以下内容:
  • JNI版本
  • ignoreUnrecognized
  • VM参数
  • VM参数个数

VM参数应该指定classpath等常用参数。

最终使用JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args);创建JVM,返回值为0,则创建成功。

3. 构建过程

mkdir build
cd build
cmake -G "Visual Studio 14 2015 Win64" ..
cmake --build .

运行

cd Debug
jvmLuncher.exe

构建RELEASE

cmake --build . -- /p:Configuration=Release

4. 参考

Cmake link_directories https://cmake.org/cmake/help/v3.0/command/link_directories.html
Cmake target_link_directories https://cmake.org/cmake/help/v3.0/command/target_link_libraries.html
Cmake FINDJNI https://cmake.org/cmake/help/v3.0/module/FindJNI.html
Java SE The Invocation API http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/invocation.html
Cmake 构建连接时报错__imp_JNI_CreateJavaVM解决 https://stackoverflow.com/questions/12528387/jni-unresolved-external-symbol-imp-jni-createjavavm-in-64-bit-compiler
Cmake 入门维基教科书
https://zh.wikibooks.org/zh-cn/CMake_%E5%85%A5%E9%96%80/%E5%BB%BA%E7%BD%AE%E8%88%87%E9%80%A3%E7%B5%90%E7%A8%8B%E5%BC%8F%E5%BA%AB
Intejllij Community native部分源码 https://github.com/JetBrains/intellij-community/tree/master/native

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值