native

native關(guān)鍵字說明其修飾的方法是一個(gè)原生態(tài)方法,方法對(duì)應(yīng)的實(shí)現(xiàn)不是在當(dāng)前文件,而是在用其他語言(如C和C++)實(shí)現(xiàn)的文件中。Java語言本身不能對(duì)操作系統(tǒng)底層進(jìn)行訪問和操作宅广,但是可以通過JNI接口調(diào)用其他語言來實(shí)現(xiàn)對(duì)底層的訪問。

凡是一種語言些举,都希望是純跟狱。比如解決某一個(gè)方案都喜歡就單單這個(gè)語言來寫即可。Java平臺(tái)有個(gè)用戶和本地C代碼進(jìn)行互操作的API户魏,稱為Java Native Interface (Java本地接口)驶臊。

http://www.cnblogs.com/Alandre/p/4456719.html

創(chuàng)建一個(gè)Java類挪挤,里面包含著一個(gè) native 的方法和加載庫的方法 loadLibrary。HelloNative.java 代碼如下:

native 關(guān)鍵字告訴編譯器(其實(shí)是JVM)調(diào)用的是該方法在外部定義关翎,這里指的是C扛门。

public class HelloNative

{static{System.loadLibrary("HelloNative");}public static native void sayHello();

@SuppressWarnings("static-access")

public static void main(String[] args){new HelloNative().sayHello();}}

那個(gè)加載庫的到后面也起作用。native 關(guān)鍵字告訴編譯器(其實(shí)是JVM)調(diào)用的是該方法在外部定義纵寝,這里指的是C论寨。如果大家直接運(yùn)行這個(gè)代碼,? JVM會(huì)告之:“A Java Exception has occurred.”控制臺(tái)輸出如下:Exception in thread "main" java.lang.UnsatisfiedLinkError: no HelloNative in java.library.path?at java.lang.ClassLoader.loadLibrary(Unknown Source)?at java.lang.Runtime.loadLibrary0(Unknown Source)?at java.lang.System.loadLibrary(Unknown Source)?at HelloNative.(HelloNative.java:5)

運(yùn)行javah爽茴,得到包含該方法的C聲明頭文件.h ? ?-> ?

根據(jù)頭文件葬凳,寫C實(shí)現(xiàn)本地方法 ?->

生成dll共享庫,然后Java程序load庫室奏,調(diào)用即可火焰。

HelloNative.h文件

/* DO NOT EDIT THIS FILE - it is machine generated */

#include

/* Header for class HelloNative */

#ifndef _Included_HelloNative

#define _Included_HelloNative

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class:???? HelloNative

* Method:??? sayHello

* Signature: ()V

*/

JNIEXPORT void JNICALL Java_HelloNative_sayHello

(JNIEnv *, jclass);

#ifdef __cplusplus

}

#endif

#endif

jni.h 這個(gè)文件,在/%JAVA_HOME%include

3胧沫、根據(jù)頭文件昌简,寫C實(shí)現(xiàn)本地方法

這里我們簡單地實(shí)現(xiàn)這個(gè)sayHello方法如下:

#include "HelloNative.h"

#include

JNIEXPORT void JNICALL Java_HelloNative_sayHello

{printf("Hello绒怨,JNI");}

生成dll共享庫纯赎,然后Java程序load庫,調(diào)用即可窖逗。在Windows上址否,MinGW GCC 運(yùn)行如下:

gcc -m64? -Wl,--add-stdcall-alias -I"C:\Program Files\Java\jdk1.7.0_71\include" -I"C:\Program Files\Java\jdk1.7.0_71\include\include\win32" -shared -o HelloNative.dll HelloNative.c

-m64表示生成dll庫是64位的。然后運(yùn)行HelloNative: java HelloNative




JNI調(diào)用C 流程

JNI是Java本機(jī)接口(JavaNativeInterface)碎紊,是一個(gè)本機(jī)編程接口佑附,它是Java軟件開發(fā)工具箱(JavaSoftware Development Kit,SDK)的一部分仗考。JNI允許Java代碼使用以其他語言編寫的代碼和代碼庫音同。Invocation API(JNI的一部分)可以用來將Java虛擬機(jī)(JVM)嵌入到本機(jī)應(yīng)用程序中,從而允許程序員從本機(jī)代碼內(nèi)部調(diào)用Java代碼秃嗜。

不過权均,對(duì)Java外部的調(diào)用通常不能移植到其他平臺(tái),在applet中還可能引發(fā)安全異常锅锨。實(shí)現(xiàn)本地代碼將使您的Java應(yīng)用程序無法通過100%純Java測試叽赊。但是,如果必須執(zhí)行本地調(diào)用必搞,則要考慮幾個(gè)準(zhǔn)則:

1.將您的所有本地方法都封裝到一個(gè)類中必指,這個(gè)類調(diào)用單個(gè)的DLL。對(duì)每一種目標(biāo)操作系統(tǒng)平臺(tái)恕洲,都可以用特定于適當(dāng)平臺(tái)的版本的DLL塔橡。這樣可以將本地代碼的影響減少到最小梅割,并有助于將以后所需要的移植問題考慮在內(nèi)。

2.本地方法盡量簡單葛家。盡量使您的本地方法對(duì)第三方(包括Microsoft)運(yùn)行時(shí)DLL的依賴減少到最小户辞。使您的本地方法盡量獨(dú)立,以將加載您的DLL和應(yīng)用程序所需的開銷減少到最小癞谒。如果需要運(yùn)行時(shí)DLL底燎,必須隨應(yīng)用程序一起提供。

JNI的書寫步驟如下:

a.編寫帶有native聲明的方法的Java

b.使用javac命令編譯編寫的Java

c.使用java-jni ****來生成后綴名為.h的頭文件

d.使用其他語言(C扯俱、C++)實(shí)現(xiàn)本地方法

e.將本地方法編寫的文件生成動(dòng)態(tài)鏈接庫

以下是一個(gè)在Java中調(diào)用本地C程序的簡單的例子:

a.編寫HelloWorld.java

class HelloWorld{

publicnativevoid hello();

static{

System.loadLibrary("hello");

}

public static void main(String[] args){

new HelloWorld().hello();

}

}

聲明native方法:如果你想將一個(gè)方法做為一個(gè)本地方法的話书蚪,那么你就必須聲明改方法為native的喇澡,并且不能實(shí)現(xiàn)迅栅。其中方法的參數(shù)和返回值在后面講述。

Load動(dòng)態(tài)庫:System.loadLibrary("hello");加載動(dòng)態(tài)庫(我們可以這樣理解:我們的方法hello()沒有實(shí)現(xiàn)晴玖,但是我們在下面就直接使用了读存,所以必須在使用之前對(duì)它進(jìn)行初始化)這里一般是以static塊進(jìn)行加載的。同時(shí)需要注意的是System.loadLibrary();的參數(shù)“hello”是動(dòng)態(tài)庫的名字呕屎。

b.編譯

javac HelloWorld.java

c.生成.h文件

javah -jni HelloWorld


示例比如說 類文件在D:\project\sparkStreamingLearn\src\main\java\TestNative\HelloWorldnative.java

使用javah 時(shí)注意執(zhí)行位置是源代碼目錄 D:\project\sparkStreamingLearn\src\让簿,

classpath是 載入類的路徑 是 D:\project\sparkStreamingLearn\src\main\java\

對(duì)應(yīng)的類為:TestNative包下的HelloWorldnative.java? -jni 路徑是包名+類名 即 TestNative\HelloWorldnative.java

-d 輸出目錄(可以任意指定) 即TestNative_HelloWorldnative.h文件的輸出目錄 當(dāng)前可以指定為D:\project\sparkStreamingLearn\src\main\java\TestNative\

結(jié)果為: D:\project\sparkStreamingLearn\src\main\java\TestNative\TestNative_HelloWorldnative.h

我們要開始寫javah的命令,以便生成對(duì)應(yīng)的C語言頭文件

D:\我的文檔\workspace\PrepareForExam\src>javah -classpath D:\我的文檔\workspace\PrepareForExam\bin -d d:/ -jni

com.example.myclass.jni_test

其中java中各個(gè)命令的意思是

-classpath <路徑> 用于裝入類的路徑

-d <目錄> 輸出目錄

-jni 生成 JNI樣式的頭文件(默認(rèn))

注意到以上我們命令中指定的路徑

注意到我們的命令符的執(zhí)行位置是源代碼目錄”D:\我的文檔\workspace\PrepareForExam\src”

-classpath? 后面的路徑是指包”com.example.myclass”所在的根路徑

-jni 后面的路徑是包名+類名



生成內(nèi)容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */

#include

/* Header for class HelloWorld */

#ifndef _Included_HelloWorld

#define _Included_HelloWorld

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class:???? HelloWorld

* Method:????hello

* Signature: ()V

*/

JNIEXPORT void JNICALLJava_HelloWorld_hello

(JNIEnv *, jobject);

#ifdef __cplusplus

}

#endif

#endif

第一個(gè)參數(shù)是調(diào)用JNI方法時(shí)使用的JNI Environment指針秀睛。第二個(gè)參數(shù)是指向在此Java代碼中實(shí)例化的Java對(duì)象HelloWorld的一個(gè)句柄尔当。其他參數(shù)是方法本身的參數(shù)

d.c實(shí)現(xiàn)

#include

#include "HelloWorld.h"

#include

JNIEXPORT void JNICALLJava_HelloWorld_hello(JNIEnv *env,jobject obj){

printf("Hello World!\n");

return;

}

其中,第一行是將jni.h文件引入(在%JAVA_HOME%\include目錄下)蹂安,里邊有JNIEnv和jobject的定義椭迎。

e.編譯c實(shí)現(xiàn)

cl -- vs201X 的安裝目錄下 Common7/Tools/Shortcuts/VS2013開發(fā)人員命令提示? 開始cl 命令行? c/c++ 編譯器 ?這里以在Windows中為例,需要生成dll文件田盈。在保存HelloWorldImpl.c文件夾下面畜号,使用VC的編譯器cl成。是-I? 搜索其后添加所需文件所在的目錄 注意需要添加"" 即"java_home%\include" -LD? 是創(chuàng)建.dll

這里以在Windows中為例允瞧,需要生成dll文件简软。在保存HelloWorldImpl.c文件夾下面,使用VC的編譯器cl成述暂。

cl -I%java_home%\include -I%java_home%\include\win32 -LD HelloWorldImp.c -Fehello.dll

注意:生成的dll文件名在選項(xiàng)-Fe后面配置痹升,這里是hello,因?yàn)樵贖elloWorld.java文件中我們loadLibary的時(shí)候使用的名字是hello畦韭。當(dāng)然這里修改之后那里也需要修改疼蛾。另外需要將-I%java_home%\include -I%java_home%\include\win32參數(shù)加上,因?yàn)樵诘谒牟嚼锩婢帉懕镜胤椒ǖ臅r(shí)候引入了jni.h文件廊驼。

6) 運(yùn)行程序

javaHelloWorld就ok了据过!


javac? 出現(xiàn)錯(cuò)誤 不是內(nèi)部或外部命令惋砂,也不時(shí)可運(yùn)行的程序? 修改path 添加 %Java_home%/bin;%Java_home%/jre/bin;

javac 出現(xiàn)中文亂碼 修改方法: javac -encoding "UTF-8" HelloWorldnative.java

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市绳锅,隨后出現(xiàn)的幾起案子西饵,更是在濱河造成了極大的恐慌,老刑警劉巖鳞芙,帶你破解...
    沈念sama閱讀 222,464評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件眷柔,死亡現(xiàn)場離奇詭異,居然都是意外死亡原朝,警方通過查閱死者的電腦和手機(jī)驯嘱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來喳坠,“玉大人鞠评,你說我怎么就攤上這事『攫模” “怎么了剃幌?”我有些...
    開封第一講書人閱讀 169,078評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長晾浴。 經(jīng)常有香客問我负乡,道長,這世上最難降的妖魔是什么脊凰? 我笑而不...
    開封第一講書人閱讀 59,979評(píng)論 1 299
  • 正文 為了忘掉前任抖棘,我火速辦了婚禮,結(jié)果婚禮上狸涌,老公的妹妹穿的比我還像新娘切省。我一直安慰自己,他們只是感情好杈抢,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評(píng)論 6 398
  • 文/花漫 我一把揭開白布数尿。 她就那樣靜靜地躺著,像睡著了一般惶楼。 火紅的嫁衣襯著肌膚如雪右蹦。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,584評(píng)論 1 312
  • 那天歼捐,我揣著相機(jī)與錄音何陆,去河邊找鬼。 笑死豹储,一個(gè)胖子當(dāng)著我的面吹牛贷盲,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 41,085評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼巩剖,長吁一口氣:“原來是場噩夢啊……” “哼铝穷!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起佳魔,我...
    開封第一講書人閱讀 40,023評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤曙聂,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后鞠鲜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宁脊,經(jīng)...
    沈念sama閱讀 46,555評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評(píng)論 3 342
  • 正文 我和宋清朗相戀三年贤姆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了榆苞。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,769評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡霞捡,死狀恐怖坐漏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情弄砍,我是刑警寧澤仙畦,帶...
    沈念sama閱讀 36,439評(píng)論 5 351
  • 正文 年R本政府宣布输涕,位于F島的核電站音婶,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏莱坎。R本人自食惡果不足惜衣式,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望檐什。 院中可真熱鬧碴卧,春花似錦、人聲如沸乃正。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瓮具。三九已至荧飞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間名党,已是汗流浹背叹阔。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留传睹,地道東北人耳幢。 一個(gè)月前我還...
    沈念sama閱讀 49,191評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像欧啤,于是被迫代替她去往敵國和親睛藻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子启上,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • native關(guān)鍵字說明其修飾的方法是一個(gè)原生態(tài)方法,方法對(duì)應(yīng)的實(shí)現(xiàn)不是在當(dāng)前文件店印,而是在用其他語言(如C和C++)...
    時(shí)待吾閱讀 567評(píng)論 0 2
  • 命題作文:對(duì)Java Native Interface (JNI) 有一個(gè)認(rèn)識(shí)碧绞,使用JNI完成一個(gè)打印輸出的工作。...
    Silly_N_Fool閱讀 1,151評(píng)論 0 4
  • native關(guān)鍵字說明其修飾的方法是一個(gè)原生態(tài)方法吱窝,方法對(duì)應(yīng)的實(shí)現(xiàn)不是在當(dāng)前文件讥邻,而是在用其他語言(如C和C++)...
    多了去的YangXuLei閱讀 1,393評(píng)論 0 2
  • 簡單地講,一個(gè)Native Method就是一個(gè)java調(diào)用非java代碼的接口院峡。一個(gè)Native Method是...
    北風(fēng)第一支閱讀 782評(píng)論 0 0
  • 螞蟻金服的今年的實(shí)習(xí)生的招聘已經(jīng)開始兴使,招聘對(duì)象為 2018 年畢業(yè)的同學(xué),歡迎大家投簡歷過來照激,投過來的簡歷我們會(huì)盡...
    khotyn閱讀 1,200評(píng)論 3 1