# JNI 介绍

参考 java11 官方文档:java-native-interface-overview

# 简单示例

# Java 调 C++

  1. Java 代码
HelloJNI.java
public class HelloJNI {
  static {
    System.loadLibrary("hello");
  }
  private native void sayHello();
  public static void main(String[] args) {
    new HelloJNI().sayHello();
  }
}
  1. 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;
}
  1. 编译
# C++ 编译
g++ -fPIC -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux" -shared -o libhello.so HelloJNI.cpp

# Java 编译
javac HelloJNI.java
  1. 运行
java -Djava.library.path=. HelloJNI

输出:

Hello World from C++!

# C++ 调 Java

  1. Java 代码
HelloJNI.java
public class HelloJNI {
  private int addOne(int number) {
    return number + 1;
  }
}
  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();
}
  1. 编译
# 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
  1. 运行
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 进行了实现。