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.htarget_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