native總結(jié)

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

凡是一種語(yǔ)言球散,都希望是純尿赚。比如解決某一個(gè)方案都喜歡就單單這個(gè)語(yǔ)言來(lái)寫(xiě)即可。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 的方法和加載庫(kù)的方法 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è)加載庫(kù)的到后面也起作用皿渗。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ù)頭文件约计,寫(xiě)C實(shí)現(xiàn)本地方法 ?->

生成dll共享庫(kù),然后Java程序load庫(kù)迁筛,調(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ù)頭文件尉桩,寫(xiě)C實(shí)現(xiàn)本地方法

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

#include "HelloNative.h"

#include

JNIEXPORT void JNICALL Java_HelloNative_sayHello

{printf("Hello贪庙,JNI");}

生成dll共享庫(kù)蜘犁,然后Java程序load庫(kù),調(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庫(kù)是64位的。然后運(yùn)行HelloNative: java HelloNative

JNI調(diào)用C 流程

JNI是Java本機(jī)接口(JavaNativeInterface)导披,是一個(gè)本機(jī)編程接口屈扎,它是Java軟件開(kāi)發(fā)工具箱(JavaSoftware Development Kit,SDK)的一部分撩匕。JNI允許Java代碼使用以其他語(yǔ)言編寫(xiě)的代碼和代碼庫(kù)鹰晨。Invocation API(JNI的一部分)可以用來(lái)將Java虛擬機(jī)(JVM)嵌入到本機(jī)應(yīng)用程序中,從而允許程序員從本機(jī)代碼內(nèi)部調(diào)用Java代碼止毕。

不過(guò)模蜡,對(duì)Java外部的調(diào)用通常不能移植到其他平臺(tái),在applet中還可能引發(fā)安全異常扁凛。實(shí)現(xiàn)本地代碼將使您的Java應(yīng)用程序無(wú)法通過(guò)100%純Java測(cè)試忍疾。但是,如果必須執(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荚孵。這樣可以將本地代碼的影響減少到最小,并有助于將以后所需要的移植問(wèn)題考慮在內(nèi)纬朝。

2.本地方法盡量簡(jiǎn)單收叶。盡量使您的本地方法對(duì)第三方(包括Microsoft)運(yùn)行時(shí)DLL的依賴減少到最小。使您的本地方法盡量獨(dú)立共苛,以將加載您的DLL和應(yīng)用程序所需的開(kāi)銷(xiāo)減少到最小判没。如果需要運(yùn)行時(shí)DLL蜓萄,必須隨應(yīng)用程序一起提供。

JNI的書(shū)寫(xiě)步驟如下:

a.編寫(xiě)帶有native聲明的方法的Java

b.使用javac命令編譯編寫(xiě)的Java

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

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

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

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

a.編寫(xiě)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)庫(kù):System.loadLibrary("hello");加載動(dòng)態(tài)庫(kù)(我們可以這樣理解:我們的方法hello()沒(méi)有實(shí)現(xiàn),但是我們?cè)谙旅婢椭苯邮褂昧嘶昊伲员仨氃谑褂弥皩?duì)它進(jìn)行初始化)這里一般是以static塊進(jìn)行加載的玻佩。同時(shí)需要注意的是System.loadLibrary();的參數(shù)“hello”是動(dòng)態(tài)庫(kù)的名字。

b.編譯

javac HelloWorld.java

c.生成.h文件

javah -jni HelloWorld

示例比如說(shuō) 類文件在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

我們要開(kāi)始寫(xiě)javah的命令咬崔,以便生成對(duì)應(yīng)的C語(yǔ)言頭文件

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開(kāi)發(fā)人員命令提示? 開(kāi)始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)樵诘谒牟嚼锩婢帉?xiě)本地方法的時(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)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末猾昆,一起剝皮案震驚了整個(gè)濱河市陶因,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌垂蜗,老刑警劉巖楷扬,帶你破解...
    沈念sama閱讀 222,378評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件解幽,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡烘苹,警方通過(guò)查閱死者的電腦和手機(jī)躲株,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)镣衡,“玉大人霜定,你說(shuō)我怎么就攤上這事±μ剑” “怎么了然爆?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,983評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)黍图。 經(jīng)常有香客問(wèn)我曾雕,道長(zhǎng),這世上最難降的妖魔是什么助被? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,938評(píng)論 1 299
  • 正文 為了忘掉前任剖张,我火速辦了婚禮,結(jié)果婚禮上揩环,老公的妹妹穿的比我還像新娘搔弄。我一直安慰自己,他們只是感情好丰滑,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布顾犹。 她就那樣靜靜地躺著,像睡著了一般褒墨。 火紅的嫁衣襯著肌膚如雪炫刷。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,549評(píng)論 1 312
  • 那天郁妈,我揣著相機(jī)與錄音浑玛,去河邊找鬼。 笑死噩咪,一個(gè)胖子當(dāng)著我的面吹牛顾彰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播胃碾,決...
    沈念sama閱讀 41,063評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼涨享,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了书在?” 一聲冷哼從身側(cè)響起灰伟,我...
    開(kāi)封第一講書(shū)人閱讀 39,991評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后栏账,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體帖族,經(jīng)...
    沈念sama閱讀 46,522評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評(píng)論 3 342
  • 正文 我和宋清朗相戀三年挡爵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了竖般。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,742評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡茶鹃,死狀恐怖涣雕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情闭翩,我是刑警寧澤挣郭,帶...
    沈念sama閱讀 36,413評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站疗韵,受9級(jí)特大地震影響兑障,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蕉汪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評(píng)論 3 335
  • 文/蒙蒙 一流译、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧者疤,春花似錦福澡、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,572評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至糯累,卻和暖如春业岁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背寇蚊。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,671評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留棍好,地道東北人仗岸。 一個(gè)月前我還...
    沈念sama閱讀 49,159評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像借笙,于是被迫代替她去往敵國(guó)和親扒怖。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評(píng)論 2 361

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

  • native關(guān)鍵字說(shuō)明其修飾的方法是一個(gè)原生態(tài)方法业稼,方法對(duì)應(yīng)的實(shí)現(xiàn)不是在當(dāng)前文件,而是在用其他語(yǔ)言(如C和C++)...
    時(shí)待吾閱讀 1,151評(píng)論 0 1
  • 命題作文:對(duì)Java Native Interface (JNI) 有一個(gè)認(rèn)識(shí),使用JNI完成一個(gè)打印輸出的工作苛萎。...
    Silly_N_Fool閱讀 1,151評(píng)論 0 4
  • _ 聲明: 對(duì)原文格式以及內(nèi)容做了細(xì)微的修改和美化, 主要為了方便閱讀和理解 _ 一. 基礎(chǔ) Java Nativ...
    元亨利貞o閱讀 5,950評(píng)論 0 34
  • 一、NDK產(chǎn)生的背景 Android平臺(tái)從誕生起骡楼,就已經(jīng)支持C、C++開(kāi)發(fā)稽鞭。眾所周知鸟整,Android的SDK基于J...
    Ten_Minutes閱讀 3,513評(píng)論 1 27
  • 2017-7-31 Whatever tickles your fancy 插一張畫(huà) 甚或會(huì)有很多人會(huì)有這樣那樣的...
    我是石老板閱讀 415評(píng)論 2 5