How to Develop Java Library
Introduction
GraphAr Java library based on GraphAr C++ library and an efficient FFI for Java and C++ called 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.
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:
# 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.
Building GraphAr Java
Please refer to GraphAr Java Library user guide.
How To Test
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. To ensure CI for checking code style will pass, please ensure check below is success:
mvn spotless:check
If there are violations, running command below to automatically format:
mvn spotless:apply