簡介
- 開發環境
- 代碼結構
- .h文件生成
- 編譯生成so文件
- 運行
- 擴展(有包名的情況)
開發環境
- centos 6.8 ×64
[root@localhost jni]# cat /proc/version
Linux version 2.6.32-696.10.2.el6.x86_64 (mockbuild@c1bl.rdu2.centos.org) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-18) (GCC) ) #1 SMP Tue Sep 12 14:33:29 UTC 2017
- jdk 1.8
目錄/usr/local/java/jdk1.8.0_144
[root@localhost jni]# java -version
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)
- g++ 4.4.7
[root@localhost jdk1.8.0_144]# g++ --version
g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-18)
Copyright ? 2010 Free Software Foundation, Inc.
本程序是自由軟件;請參看源代碼的版權聲明。本軟件沒有任何擔保;
包括沒有適銷性和某一專用目的下的適用性擔保。
代碼結構
為了方便大家能夠快速入門,先寫一個簡單的示例來演示。
先看下代碼結構:
1.png
- JavaMain.java java源代碼
- CppLib.cpp C++源代碼
- JavaMain.h 是由JavaMain.java生成的頭文件
.h文件生成
public class JavaMain{
public static void main(String[] args){
System.out.println("Ok!");
new JavaMain().show();
}
public native void show();
static{
System.loadLibrary("cpp");
}
}
代碼很簡單,native來聲明該方法非java方法。static代碼塊來加載動態庫。
接下來就是生成.h文件。直接執行
javah JavaMain.java
生成JavaMain.h頭文件
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JavaMain */
#ifndef _Included_JavaMain
#define _Included_JavaMain
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: JavaMain
* Method: show
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_JavaMain_show
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
編譯生成so文件
接下來就是引入頭文件進行C/C++編碼。
#include "JavaMain.h"
#include "jni.h"
JNIEXPORT void JNICALL Java_JavaMain_show
(JNIEnv * env, jobject jb){
printf("%s","cpp library\n");
}
內容很簡單,就是打印一句話。
接下來就是編譯,為了方便,我們使用make工具來執行編譯過程。這里需要編寫Makefile。對Makefile不熟的兄弟可以參考Makefile文件編寫。對g++不熟的兄弟可以參考gcc編譯參數
libcpp.so : CppLib.cpp
g++ -o $@ $+ -fPIC -shared -I/usr/local/java/jdk1.8.0_144/include -I/usr/local/java/jdk1.8.0_144/include/linux
.PHONY : clean
clean :
-rm libcpp.so
這里主要有幾個參數需要注意
-
-fPIC -shared
代表編譯成動態庫 -
-I/usr/local/java/jdk1.8.0_144/include -I/usr/local/java/jdk1.8.0_144/include/linux
引入jni相關的頭文件。我的jdk就安裝在/usr/local/java/jdk1.8.0_144
下
接下來就是編譯,直接執行make
命令,成功生成libcpp.so
文件。linux下庫文件有個特點就是固定以lib開頭,.so
為擴展名。
運行
得到so文件后,接下來就編譯JavaMain.java。執行
javac JavaMain.java
得到JavaMain.class
執行:
java -Djava.library.path='.' JavaMain
java一般使用兩個path:classpath 和 java.library.path
classpath是指向jar包的位置
java.library.path是非java類包的位置如(dll,so)
結果:
[root@localhost jni]# java -Djava.library.path='.' JavaMain
Ok!
cpp library
擴展(有包名的情況)
有不少兄弟在正常的項目開發中,javah和java命令會出現各種錯誤,比如"找不到**類"。這里我就做一個完整的示例。
2.png
有以下幾點需要注意:
- 執行javah和java命令要在源碼目錄下,也就是src/java目錄下。
- 執行java命令來運行時候,需要制定java.library.path的路徑。
/**
* 在java目錄下
*
* 生成頭文件
* javah com.eric.demo.JavaMain
*
* 編譯
* javac com.eric.demo.JavaMain.java
*
* 運行
* java com.eric.demo.JavaMain -Djava.library.path=/code/jni2/src/main/jni
*/