OSRM-backend를 참고하여 OSRM 라이브러리를 설치한다.
- 예시(Ubuntu 22.04. 소스코드 빌드)
eraser@eraser-tmax:/usr/local/lib$ ll | grep osrm total 34856 drwxr-xr-x 4 root root 4096 5월 27 15:41 ./ drwxr-xr-x 10 root root 4096 4월 19 19:02 ../ -rw-r--r-- 1 root root 8759280 5월 27 15:40 libosrm.a -rw-r--r-- 1 root root 2106694 5월 27 15:41 libosrm_contract.a -rw-r--r-- 1 root root 1912114 5월 27 15:41 libosrm_customize.a -rw-r--r-- 1 root root 12127312 5월 27 15:40 libosrm_extract.a -rw-r--r-- 1 root root 3410924 5월 27 15:40 libosrm_guidance.a -rw-r--r-- 1 root root 2315194 5월 27 15:40 libosrm_partition.a -rw-r--r-- 1 root root 2342522 5월 27 15:41 libosrm_store.a -rw-r--r-- 1 root root 2690284 5월 27 15:41 libosrm_update.a
JNI 인터페이스를 호출하여 OSRM C++ native code에 접근하기 위한 Java class를 작성한다.
- native 코드에서 호출할 메서드의 시그니처를 작성한다
- 메서드 몸체는 작성하지 않는다. 작성 시
native methods do not specify body
와 같은 컴파일 에러 발생
- 메서드 몸체는 작성하지 않는다. 작성 시
- java class에서의 메서드 시그니처 함수 파라미터 타입과 native 코드 함수 시그니처 파라미터 타입에 주의한다
- primitive type의 경우 값이 복사되나, reference type의 경우 jvm과 native 메모리 상에서 참조 주소를 전달하는 것에 주의 필요
- JNI Types and Data Structures 참고
public class OsrmJNI {
private native int main();
public int returnMain() {
return main();
}
}
Java Application에서 C++ native module을 호출하기 위한 헤더 파일을 생성한다.
- 자바 소스 코드 컴파일:
javac OsrmJNI.java
- 헤더 파일 생성:
javac -h . OsrmJNI.java
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_eraser_jniosrm_OsrmJNI */
#ifndef _Included_com_eraser_jniosrm_OsrmJNI
#define _Included_com_eraser_jniosrm_OsrmJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_eraser_jniosrm_OsrmJNI
* Method: main
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_eraser_jniosrm_OsrmJNI_main
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
C++ 라이브러리를 이용해 수행할 코드를 작성한다.
컴파일 및 링킹을 통해, .so
파일을 생성한다. 이 프로젝트에서는 OSRM backend에서 제공하는 컴파일 방식을 참고해, CMakeLists.txt
를 변경해 빌드했다.
- 참고: CMakeList.txt for building OSRM C++ example
- Cmake 이용 빌드
- g++ 컴파일러 사용:
-DCMAKE_CXX_COMPILER
- 멀티 쓰레드 옵션:
-DREENTRANT
- g++ 컴파일러 사용:
mkdir build
cmake -DCMAKE_CXX_COMPILER=/usr/bin/g++ ..
cmake --build .
# generated build script
/usr/bin/g++ -fPIC -std=c++14 -DBOOST_TEST_DYN_LINK -DBOOST_SPIRIT_USE_PHOENIX_V3 -DBOOST_RESULT_OF_USE_DECLTYPE -DBOOST_FILESYSTEM_NO_DEPRECATED -I/usr/include/lua5.2 -I/usr/local/include -I/usr/local/include/osrm -D_REENTRANT -O3 -DNDEBUG -shared -Wl,-soname,libosrmjni.so -o libosrmjni.so CMakeFiles/osrmjni.dir/osrmJNI.cpp.o -L/usr/local/lib -losrm -fuse-ld=gold -Wl,--disable-new-dtags -Wl,--gc-sections -Wl,-O1 -Wl,--hash-style=gnu -Wl,--sort-common -L/usr/local/lib -losrm -fuse-ld=gold -Wl,--disable-new-dtags -Wl,--gc-sections -Wl,-O1 -Wl,--hash-style=gnu -Wl,--sort-common /usr/lib/x86_64-linux-gnu/libboost_regex.so.1.74.0 /usr/lib/x86_64-linux-gnu/libboost_date_time.so.1.74.0 /usr/lib/x86_64-linux-gnu/libboost_chrono.so.1.74.0 /usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.74.0 /usr/lib/x86_64-linux-gnu/libboost_iostreams.so.1.74.0 /usr/lib/x86_64-linux-gnu/libboost_thread.so.1.74.0 /usr/lib/x86_64-linux-gnu/libboost_system.so.1.74.0 -ltbb -ltbbmalloc -lrt -lz
자바 어플리케이션에서 빌드한 C++ shared library를 로드한다.
public class OsrmJNI {
private native int main();
public int returnMain() {
return main();
}
// load library as static
static {
System.load("/home/eraser/projects/osrm-jni/jniosrm/src/src++/build/libosrmjni-example.so");
}
}
C++ native code에서 객체를 생성하였다면,
- JVM으로 반환되는 경우
- JVM으로 반환되지 않고 더 이상 사용되지 않는 경우
local reference로 생성되는 것들은 굳이 해제하지 않아도 된다. 잘못 해제하면 jfieldID
등 reference가 없어서 오류 발생
- OSRM thread-safe 확인
- Java application
System.loadLibrary
vs.System.load