1. 程式人生 > 程式設計 >詳解Java中native方法的使用

詳解Java中native方法的使用

今天在網上學習時碰到有關於 native修飾符所修飾的方法,上網查了查,覺得很有意思記錄一下

在這裡插入圖片描述

1、native簡介

簡單地講,一個Native Method就是一個java呼叫非java程式碼的介面。一個Native Method是這樣一個java的方法:該方法的實現由非java語言實現,比如C。這個特徵並非java所特有,很多其它的程式語言都有這一機制,比如在C++中,你可以用extern “C”告知C++編譯器去呼叫一個C的函式。

native是與C++聯合開發的時候用的!使用native關鍵字說明這個方法是原生函式,也就是這個方法是用C/C++語言實現的,並且被編譯成了DLL,由java去呼叫。 這些函式的實現體在DLL中,JDK的原始碼中並不包含,你應該是看不到的。對於不同的平臺它們也是不同的。這也是java的底層機制,實際上java就是在不同的平臺上呼叫不同的native方法實現對作業系統的訪問的。總而言之:

native 是用做java 和其他語言(如c++)進行協作時使用的,也就是native 後的函式的實現不是用java寫的。
既然都不是java,那就別管它的原始碼了,我們只需要知道這個方法已經被實現即可。
native的意思就是通知作業系統, 這個函式你必須給我實現,因為我要使用。 所以native關鍵字的函式都是作業系統實現的, java只能呼叫。
java是跨平臺的語言,既然是跨了平臺,所付出的代價就是犧牲一些對底層的控制,而java要實現對底層的控制,就需要一些其他語言的幫助,這個就是native的作用了。

2、native用法

1.編寫帶有native宣告的方法的Java類(java檔案)

2.使用javac命令編譯編寫的Java類(class檔案)如:javac NativeTest.java
3.使用javah -jni ****來生成字尾名為.h的標頭檔案(.h的檔案) 如:javah -jni NativeTest
4.使用其他語言(C、C++)實現本地方法
5.將本地方法編寫的檔案生成動態連結庫(dll檔案)

注意:javac NativeTest.java 沒有帶包名,因為我的NativeTest.java不在任何包(package)中。

示例如下:

public class NativeTest {
 public native void hello(String name);
 static{
  System.loadLibrary("wittdong");//wittdong和生成動態連結庫的 wittdong.dll名字一致
 }
 public static void main(String[] args){
  new NativeTest().hello("jni");
 }
}

在這裡插入圖片描述

開啟 javah 編譯出 字尾名為 .h 的檔案圖:

在這裡插入圖片描述

4、用C語言實現本地方法(hello),生成 NativeTestImpl.c 格式檔案

#include <jni.h>
#include “NativeTest.h”
#include <stdio.h>
JNIEXPORT void JNICALL Java_NativeTest_hello(JNIEnv *env,jobject obj,jstring name){
printf(“hello world”);
}

5、生成動態連結庫

一種方式:cl -I %java_home%\include -I%java_home%\include\win32 -LD NativeTestImpl.c -Fe wittdong.dll

另一種方式:用VC++6.0編譯一下在debug資料夾中就生成好了dll檔案。

將dll放到生成.h的那一級資料夾中,就可以進行native本地方法呼叫。在Eclipse執行時,需把dll檔案拷貝到C:\Windows\System32

3、補充資料

c語言中.c和.h檔案關係以及區別:

本質上沒有任何區別。 只不過一般:.h檔案是標頭檔案,內含函式宣告、巨集定義、結構體定義等內容

.c檔案是程式檔案,內含函式實現,變數定義等內容。而且是什麼字尾也沒有關係,只不過編譯器會預設對某些字尾的檔案採取某些動作。你可以強制編譯器把任何字尾的檔案都當作c檔案來編。

這樣分開寫成兩個檔案是一個良好的程式設計風格。

而且,比方說 我在aaa.h裡定義了一個函式的宣告,然後我在aaa.h的同一個目錄下建立aaa.c ,aaa.c裡定義了這個函式的實現,然後是在main函式所在.c檔案裡#include這個aaa.h 然後我就可以使用這個函數了。 main在執行時就會找到這個定義了這個函式的aaa.c檔案。

這是因為:

main函式為標準C/C++的程式入口,編譯器會先找到該函式所在的檔案。

假定編譯程式編譯myproj.c(其中含main())時,發現它include了mylib.h(其中聲明瞭函式void test()),那麼此時編譯器將按照事先設定的路徑(Include路徑列表及程式碼檔案所在的路徑)查詢與之同名的實現檔案(副檔名為.cpp或.c,此例中為mylib.c)(應該是跟java的import一樣),如果找到該檔案,並在其中找到該函式(此例中為void test())的實現程式碼,則繼續編譯;如果在指定目錄找不到實現檔案,或者在該檔案及後續的各include檔案中未找到實現程式碼,則返回一個編譯錯誤.其實include的過程完全可以"看成"是一個檔案拼接的過程,將宣告和實現分別寫在標頭檔案及C檔案中,或者將二者同時寫在標頭檔案中,理論上沒有本質的區別。

到此這篇關於詳解Java中native方法的使用的文章就介紹到這了,更多相關java 中native方法使用內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!