| --- |
| id: how_to_develop_java_ffi |
| title: How to Develop Java FFI Library |
| sidebar_position: 2 |
| --- |
| |
| ## Introduction |
| |
| GraphAr Java library based on GraphAr C++ library and an efficient FFI |
| for Java and C++ called |
| [FastFFI](https://github.com/alibaba/fastFFI). |
| |
| ### Source Code Level |
| |
| - Interface |
| - Class |
| - JNI code |
| - GraphAr C++ library |
| |
| If you want to use classes or functions of GraphAr C++ library through |
| JAVA SDK, you only need to write interfaces with annotations. After the |
| interfaces are ready, the java code for the interfaces and the the C++ |
| code which include JNI code for native methods will be automatically |
| generated by FastFFI.For annotation’s usage, please refer to |
| [FastFFI](https://github.com/alibaba/fastFFI). |
| |
| ### Runtime Level |
| |
| Interfaces and classes will be compiled to bytecode. Usually, JNI code |
| will be compiled to bitcode as a part of dynamic library which can be |
| called by native methods directly. If llvm4jni is enable, suitable |
| method in JNI will be transferred to bytecode. |
| |
| For decoupling the implementation of C++ and Java, we use a bridge |
| dynamic library called gar-jni to connect them, it will integrate all |
| C++ dependencies(e.g. JNI code, GraphAr C++ library and arrow C++) and |
| can be called by native methods in Java directly. Most JNI code is |
| generated by FastFFI, but some JNI code is written by ourselves, such as |
| JNI code for transferring VectorSchemaRoot into arrow::Table. |
| |
| To build the bridge dynamic library, here is main part of our CMakeLists.txt: |
| |
| ```cmake |
| # set auto-generated JNI code and handwriting JNI code as source files |
| file(GLOB SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/target/generated-sources/annotations/*.cc" "${CMAKE_CURRENT_SOURCE_DIR}/target/generated-test-sources/test-annotations/*.cc" |
| "${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/ffi/*.cc") |
| # remove auto-generated JNI code for specific method cause we have handwriting JNI code for it |
| list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/target/generated-sources/annotations/jni_com_alibaba_graphar_arrow_ArrowTable_Static_cxx_0x58c7409.cc") |
| |
| set(LIBNAME "gar-jni") |
| |
| # find JNI related libraries |
| find_package(JNI REQUIRED) |
| include_directories(SYSTEM ${JAVA_INCLUDE_PATH}) |
| include_directories(SYSTEM ${JAVA_INCLUDE_PATH2}) |
| |
| # some JNI code depends on arrow |
| find_package(Arrow REQUIRED) |
| # build graphar-cpp in specific version |
| include(graphar-cpp) |
| build_graphar_cpp() |
| |
| # build the bridge JNI library |
| add_library(${LIBNAME} SHARED ${SOURCES}) |
| # include graphar-cpp headers |
| target_include_directories(${LIBNAME} SYSTEM BEFORE PRIVATE ${GRAPHAR_INCLUDE_DIR}) |
| # link graphar-cpp and arrow |
| target_link_libraries(${LIBNAME} ${CMAKE_JNI_LINKER_FLAGS} gar_shared) |
| target_link_libraries(${LIBNAME} ${CMAKE_JNI_LINKER_FLAGS} Arrow::arrow_static) |
| ``` |
| |
| More about usage of CMake, please refer to |
| [CMake's official website](https://cmake.org/). |
| |
| ## Building GraphAr Java |
| |
| Please refer to |
| [GraphAr Java Library user guide](getting-started). |
| |
| ## How To Test |
| |
| ```bash |
| export GAR_TEST_DATA=$PWD/../../testing/ |
| mvn clean test |
| ``` |
| |
| This will build GraphAr C++ library internally for Java. If you already |
| installed GraphAr C++ library in your system, you can append this option |
| to skip: `-DbuildGarCPP=OFF`. |
| |
| ## Code Style |
| |
| We follow |
| [AOSP Java code style](https://source.android.com/docs/setup/contribute/code-style). |
| To ensure CI for checking code style will pass, please ensure check |
| below is success: |
| |
| ```bash |
| mvn spotless:check |
| ``` |
| |
| If there are violations, running command below to automatically format: |
| |
| ```bash |
| mvn spotless:apply |
| ``` |