欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Java 本地接口 JNI 使用方法

 更新時(shí)間:2017年09月07日 11:08:54   作者:攻城獅--晴明  
這篇文章主要介紹了詳解Java 本地接口 JNI 使用方法的相關(guān)資料,希望通過(guò)本文大家能徹底使用JNI編程,需要的朋友可以參考下

詳解Java 本地接口 JNI 使用方法

對(duì)于Java程序員來(lái)說(shuō),Java語(yǔ)言的好處和優(yōu)點(diǎn),我想不用我說(shuō)了,大家自然會(huì)說(shuō)出很多一套套的。但雖然我們作為java程序員,但我們不得不承認(rèn)java語(yǔ)言也有一些它本身的缺點(diǎn)。比如在性能、和底層打交道方面都有它的缺點(diǎn)。所以java就提供了一些本地接口,他主要的作用就是提供一個(gè)標(biāo)準(zhǔn)的方式讓java程序通過(guò)虛擬機(jī)與原生代碼進(jìn)行交互,這也就是我們平常常說(shuō)的java本地接口(JNI——java native Interface)。它使得在 Java 虛擬機(jī) (VM) 內(nèi)部運(yùn)行的 Java 代碼能夠與用其它編程語(yǔ)言(如 C、C++ 和匯編語(yǔ)言)編寫的應(yīng)用程序和庫(kù)進(jìn)行互操作。JNI 最重要的好處是它沒有對(duì)底層 Java 虛擬機(jī)的實(shí)現(xiàn)施加任何限制。因此,Java虛擬機(jī)廠商可以在不影響虛擬機(jī)其它部分的情況下添加對(duì) JNI 的支持。程序員只需編寫一種版本的本地應(yīng)用程序或庫(kù),就能夠與所有支持 JNI 的 Java 虛擬機(jī)協(xié)同工作。我們來(lái)看一下為什么要與原生代碼進(jìn)行交互:

一:提高應(yīng)用程序性能。我們知道java對(duì)于c/c++、匯編語(yǔ)言來(lái)說(shuō),顯得比較“高級(jí)”。其實(shí)這里的高級(jí)就是簡(jiǎn)化了程序員的工作。很多底層的東西都讓java虛擬機(jī)做了。但畢竟相對(duì)于直接訪問底層來(lái)講,java多了一步虛擬機(jī)的過(guò)程,所以在性能上比著這些原生語(yǔ)言稍微有點(diǎn)慢。

二:實(shí)現(xiàn)一些與底層相關(guān)的功能。Java平臺(tái)提供的標(biāo)準(zhǔn)類庫(kù),還有強(qiáng)大的API,雖然能完成大部分功能。但有些和底層硬件打交道的功能在java API提供的類庫(kù)中還是無(wú)法完成。

三:與已有的使用原生代碼編寫的程序進(jìn)行集成。在于操作系統(tǒng)上由c或者c++等原生語(yǔ)言編寫的軟件進(jìn)行集 0成的時(shí)候,可以用JNI。

JNI 接口函數(shù)和指針

     平臺(tái)相關(guān)代碼是通過(guò)調(diào)用 JNI 函數(shù)來(lái)訪問 Java 虛擬機(jī)功能的。JNI 函數(shù)可通過(guò)接口指針來(lái)獲得。接口指針是指針的指針,它指向一個(gè)指針數(shù)組,而指針數(shù)組中的每個(gè)元素又指向一個(gè)接口函數(shù)。每個(gè)接口函數(shù)都處在數(shù)組的某個(gè)預(yù)定偏移量中。下圖說(shuō)明了接口指針的組織結(jié)構(gòu)。

                  

           JNI 接口的組織類似于 C++ 虛擬函數(shù)表或 COM 接口。使用接口表而不使用硬性編入的函數(shù)表的好處是使 JNI 名字空間與平臺(tái)相關(guān)代碼分開。虛擬機(jī)可以很容易地提供多個(gè)版本的 JNI 函數(shù)表。例如,虛擬機(jī)可支持以下兩個(gè) JNI 函數(shù)表:

· 一個(gè)表對(duì)非法參數(shù)進(jìn)行全面檢查,適用于調(diào)試程序;

· 另一個(gè)表只進(jìn)行 JNI 規(guī)范所要求的最小程度的檢查,因此效率較高。

JNI 接口指針只在當(dāng)前線程中有效。因此,本地方法不能將接口指針從一個(gè)線程傳遞到另一個(gè)線程中。實(shí)現(xiàn) JNI 的虛擬機(jī)可將本地線程的數(shù)據(jù)分配和儲(chǔ)存在 JNI 接口指針?biāo)赶虻膮^(qū)域中。

本地方法將JNI 接口指針當(dāng)作參數(shù)來(lái)接受。虛擬機(jī)在從相同的 Java 線程中對(duì)本地方法進(jìn)行多次調(diào)用時(shí),保證傳遞給該本地方法的接口指針是相同的。但是,一個(gè)本地方法可被不同的 Java 線程所調(diào)用,因此可以接受不同的 JNI 接口指針。                     

(1)編寫Java類代碼

    其中,需要JNI實(shí)現(xiàn)的方法應(yīng)當(dāng)用native關(guān)鍵字聲明。在該類中,用System.1oadLibrary()方法加載需要的動(dòng)態(tài)鏈接庫(kù)。關(guān)鍵代碼如下:  

 //Compute.java
 public class Compute{
 public native double sqrt(double params);
 static{
 //調(diào)用動(dòng)態(tài)鏈接庫(kù)
 System.loadLibrary(“compute”);
 }

  (2)編譯成字節(jié)代碼

    在這個(gè)過(guò)程中,由于采用了native關(guān)鍵字聲明,Java編譯器會(huì)忽視沒有代碼體的JNI方法部分。   

 (3)生成相關(guān)JNI方法的頭文件

    這個(gè)過(guò)程的實(shí)現(xiàn)一般是通過(guò)利用jlavah-jni  * class生成的(-jni可以省略),也可以手工生成該文件;但是由于 Java 虛擬機(jī)是根據(jù)一定的命名規(guī)范完成對(duì)JNI方法的調(diào)用,所以手工編寫頭文件需要特別小心。

    上述文件產(chǎn)生的頭文件部分代碼如下: 

 //Compute.h
 extern“C”{
 JNIEXPORT jdoubleJNICALL Java_Compute_comp(JNI-Env *, jobject, jdoubleArray);

    JNI函數(shù)名稱分為三部分:首先是Java關(guān)鍵字,供Java虛擬機(jī)識(shí)別;然后是調(diào)用者類名稱(全限定的類名,其中用下劃線代替名稱分隔符);最后是對(duì)應(yīng)的方法名稱,各段名稱之間用下劃線分割。

    JNI函數(shù)的參數(shù)也由三部分組成:首先是JNIEnv *,是一個(gè)指向JNI運(yùn)行環(huán)境的指針;第二個(gè)參數(shù)隨本地方法是靜態(tài)還是非靜態(tài)而有所不同一一非靜態(tài)本地方法的第二個(gè)參數(shù)是對(duì)對(duì)象的引用,而靜態(tài)本地方法的第二個(gè)參數(shù)是對(duì)其Java類的引用;其余的參數(shù)對(duì)應(yīng)通常Java方法的參數(shù),參數(shù)類型需要根據(jù)一定規(guī)則進(jìn)行映射。

    (4)編寫相應(yīng)方法的實(shí)現(xiàn)代碼

    在編碼過(guò)程中,需要注意變量的長(zhǎng)度問題,例如Java的整型變量長(zhǎng)度為32位,而C語(yǔ)言為16位,所以要仔細(xì)核對(duì)變量類型映射表,防止在傳值過(guò)程中出現(xiàn)問題。

    (5)將JNI實(shí)現(xiàn)代碼編譯成動(dòng)態(tài)鏈接庫(kù)

    編譯過(guò)程是利用C/C++編譯器實(shí)現(xiàn)的,在windows平臺(tái)上,編譯和連接的結(jié)果是動(dòng)態(tài)鏈接庫(kù)DLL文件。當(dāng)要使用生成的動(dòng)態(tài)鏈接庫(kù)時(shí),調(diào)用者類中需要顯式調(diào)用該鏈接庫(kù)dll文件。

    經(jīng)過(guò)上述處理,基本上完成了一個(gè)包含本地化方法的Java類的開發(fā)。

附錄:將Jav類型映射到本地 C 類型

 基本類型和本地等效類型

Java 類型

本地類型

說(shuō)明

boolean

jboolean

無(wú)符號(hào),8 位

byte

jbyte

無(wú)符號(hào),8 位

char

jchar

無(wú)符號(hào),16 位

short

jshort

有符號(hào),16 位

int

jint

有符號(hào),32 位

long

jlong

有符號(hào),64 位

float

jfloat

32 位

double

jdouble

64 位

void

void

N/A

為了使用方便,特提供以下定義。

 #define JNI_FALSE 0
 #define JNI_TRUE 1

jsize 整數(shù)類型用于描述主要指數(shù)和大?。?br />

typedef jint jsize;

故障排除

當(dāng)使用 JNI 從 Java 程序訪問本機(jī)代碼時(shí),您會(huì)遇到許多問題。您會(huì)遇到的三個(gè)最常見的錯(cuò)誤是:

1)無(wú)法找到動(dòng)態(tài)鏈接。它所產(chǎn)生的錯(cuò)誤消息是:java.lang.UnsatisfiedLinkError。這通常指無(wú)法找到共享庫(kù),或者無(wú)法找到共享庫(kù)內(nèi)特定的本機(jī)方法。

2)無(wú)法找到共享庫(kù)文件。當(dāng)用 System.loadLibrary(String libname) 方法(參數(shù)是文件名)裝入庫(kù)文件時(shí),請(qǐng)確保文件名拼寫正確以及沒有指定擴(kuò)展名。還有,確保庫(kù)文件的位置在類路徑中,從而確保 JVM 可以訪問該庫(kù)文件。

3)無(wú)法找到具有指定說(shuō)明的方法。確保您的 C/C++ 函數(shù)實(shí)現(xiàn)擁有與頭文件中的函數(shù)說(shuō)明相同的說(shuō)明。

結(jié)束語(yǔ)

            從 Java 調(diào)用 C 或 C++ 本機(jī)代碼(雖然不簡(jiǎn)單)是 Java 平臺(tái)中一種良好集成的功能。雖然 JNI 支持 C 和 C++,但 C++ 接口更清晰一些并且通常比 C 接口更可取。正如您已經(jīng)看到的,調(diào)用 C 或 C++ 本機(jī)代碼需要賦予函數(shù)特殊的名稱,并創(chuàng)建共享庫(kù)文件。當(dāng)利用現(xiàn)有代碼庫(kù)時(shí),更改代碼通常是不可取的。要避免這一點(diǎn),在 C++ 中,通常創(chuàng)建代理代碼或代理類,它們有專門的 JNI 所需的命名函數(shù)。然后,這些函數(shù)可以調(diào)用底層庫(kù)函數(shù),這些庫(kù)函數(shù)的說(shuō)明和實(shí)現(xiàn)保持不變。

如有疑問請(qǐng)留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!

相關(guān)文章

  • Java中File類方法詳解以及實(shí)踐

    Java中File類方法詳解以及實(shí)踐

    Java File類的功能非常強(qiáng)大,利用java基本上可以對(duì)文件進(jìn)行所有操作,下面這篇文章主要給大家介紹了關(guān)于Java中File類方法以及實(shí)踐的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-04-04
  • 詳解在SpringBoot應(yīng)用中獲取應(yīng)用上下文方法

    詳解在SpringBoot應(yīng)用中獲取應(yīng)用上下文方法

    本篇文章主要介紹了詳解在SpringBoot應(yīng)用中獲取應(yīng)用上下文方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-04-04
  • springboot?項(xiàng)目啟動(dòng)后無(wú)日志輸出直接結(jié)束的解決

    springboot?項(xiàng)目啟動(dòng)后無(wú)日志輸出直接結(jié)束的解決

    這篇文章主要介紹了springboot?項(xiàng)目啟動(dòng)后無(wú)日志輸出直接結(jié)束的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • springboot 集成支付寶支付的示例代碼

    springboot 集成支付寶支付的示例代碼

    這篇文章主要介紹了springboot 集成支付寶支付的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • 深入理解Java中的裝箱和拆箱

    深入理解Java中的裝箱和拆箱

    這篇文章主要介紹了深入理解Java中的裝箱和拆箱,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • Spring init-method與destroy-method屬性的用法解析

    Spring init-method與destroy-method屬性的用法解析

    這篇文章主要介紹了Spring init-method與destroy-method屬性的用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • SpringSecurity的@EnableWebSecurity注解詳解

    SpringSecurity的@EnableWebSecurity注解詳解

    這篇文章主要介紹了SpringSecurity的@EnableWebSecurity注解詳解,@EnableWebSecurity是開啟SpringSecurity的默認(rèn)行為,它的上面有一個(gè)Import注解導(dǎo)入了WebSecurityConfiguration類,就是往IOC容器中注入了WebSecurityConfiguration這個(gè)類,需要的朋友可以參考下
    2023-11-11
  • 使用@TransactionalEventListener監(jiān)聽事務(wù)教程

    使用@TransactionalEventListener監(jiān)聽事務(wù)教程

    這篇文章主要介紹了使用@TransactionalEventListener監(jiān)聽事務(wù)教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Springboot整合minio實(shí)現(xiàn)文件服務(wù)的教程詳解

    Springboot整合minio實(shí)現(xiàn)文件服務(wù)的教程詳解

    這篇文章主要介紹了Springboot整合minio實(shí)現(xiàn)文件服務(wù)的教程,文中的示例代碼講解詳細(xì),對(duì)我們的工作或?qū)W習(xí)有一定幫助,需要的可以參考一下
    2022-06-06
  • Spring中屬性文件properties的讀取與使用詳解

    Spring中屬性文件properties的讀取與使用詳解

    這篇文章主要介紹了Spring中屬性文件properties的讀取與使用詳解的相關(guān)資料,需要的朋友可以參考下
    2017-02-02

最新評(píng)論