# JNI 介绍
参考 java11 官方文档:java-native-interface-overview
# 简单示例
# Java 调 C++
- Java 代码
HelloJNI.java | public class HelloJNI { |
| static { |
| System.loadLibrary("hello"); |
| } |
| |
| private native void sayHello(); |
| |
| public static void main(String[] args) { |
| new HelloJNI().sayHello(); |
| } |
| } |
- C++ 代码
HelloJNI.h | #include <jni.h> |
| |
| #ifndef _Included_HelloJNI |
| #define _Included_HelloJNI |
| |
| extern "C" { |
| JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv* env, jobject obj); |
| } |
| |
| #endif |
HelloJNI.cpp | #include <jni.h> |
| #include <iostream> |
| #include "HelloJNI.h" |
| |
| using namespace std; |
| |
| JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv* env, jobject obj) { |
| cout << "Hello World from C++!" << endl; |
| } |
- 编译
# C++ 编译
g++ -fPIC -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux" -shared -o libhello.so HelloJNI.cpp
# Java 编译
javac HelloJNI.java
- 运行
java -Djava.library.path=. HelloJNI
输出:
Hello World from C++!
# C++ 调 Java
- Java 代码
HelloJNI.java | public class HelloJNI { |
| private int addOne(int number) { |
| return number + 1; |
| } |
| } |
- C++ 代码
main.cpp | #include <jni.h> |
| #include <iostream> |
| |
| using namespace std; |
| |
| int main() { |
| JavaVM* jvm; |
| JNIEnv* env; |
| JavaVMInitArgs vm_args; |
| JavaVMOption* options = new JavaVMOption[1]; |
| options[0].optionString = "-Djava.class.path=./"; |
| vm_args.version = JNI_VERSION_1_6; |
| vm_args.nOptions = 1; |
| vm_args.options = options; |
| vm_args.ignoreUnrecognized = false; |
| JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); |
| delete options; |
| jclass cls = env->FindClass("HelloJNI"); |
| jmethodID mid_constructor = env->GetMethodID(cls, "<init>", "()V"); |
| jobject obj = env->NewObject(cls, mid_constructor); |
| jmethodID mid = env->GetMethodID(cls, "addOne", "(I)I"); |
| jint result = env->CallIntMethod(obj, mid, 1); |
| cout << result << endl; |
| jvm->DestroyJavaVM(); |
| } |
- 编译
# Java 编译
javac HelloJNI.java
# C++ 编译
g++ -o main -I/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.332.b09-1.el7_9.x86_64/include -I/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.332.b09-1.el7_9.x86_64/include/linux -I/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.332.b09-1.el7_9.x86_64/jre/lib/amd64/server -L/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.332.b09-1.el7_9.x86_64/jre/lib/amd64 -L/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.332.b09-1.el7_9.x86_64/jre/lib/amd64/server -ljvm main.cpp
- 运行
export LD_LIBRARY_PATH=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.332.b09-1.el7_9.x86_64/jre/lib/amd64:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.332.b09-1.el7_9.x86_64/jre/lib/amd64/server:$LD_LIBRARY_PATH
./main
输出:
2
# impala 实现
impala 中,impalad 和 catalogd 使用到了 JNI,statestored 只有 C++。
对于 C++ 调 Java,frontend.h 和 frontend.cc 定义了调用 Java 方法的接口,JniFrontend.java 是 Java 中的实现。catalogd 中对应的分别是 catalog.h、catalog.cc 和 JniCatalog.java。
对于 Java 调 C++,FeSupport.java 定义了 Native 方法,fe-support.h 和 fe-support.cc 进行了实现。