欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
JNI的替代者

1. JNA簡(jiǎn)單介紹

先說(shuō)JNI(Java Native Interface)吧,有過(guò)不同語(yǔ)言間通信經(jīng)歷的一般都知道,它允許Java代碼和其他語(yǔ)言(尤其C/C++)寫(xiě)的代碼進(jìn)行交互,只要遵守調用約定即可。首先看下JNI調用C/C++的過(guò)程,注意寫(xiě)程序時(shí)自下而上,調用時(shí)自上而下。

 

可 見(jiàn)步驟非常的多,很麻煩,使用JNI調用.dll/.so共享庫都能體會(huì )到這個(gè)痛苦的過(guò)程。如果已有一個(gè)編譯好的.dll/.so文件,如果使用JNI技 術(shù)調用,我們首先需要使用C語(yǔ)言另外寫(xiě)一個(gè).dll/.so共享庫,使用SUN規定的數據結構替代C語(yǔ)言的數據結構,調用已有的 dll/so中公布的函 數。然后再在Java中載入這個(gè)庫dll/so,最后編寫(xiě)Java  native函數作為鏈接庫中函數的代理。經(jīng)過(guò)這些繁瑣的步驟才能在Java中調用 本地代碼。因此,很少有Java程序員愿意編寫(xiě)調用dll/.so庫中原生函數的java程序。這也使Java語(yǔ)言在客戶(hù)端上乏善可陳,可以說(shuō)JNI是 Java的一大弱點(diǎn)!

那么JNA是什么呢?

JNA(Java Native Access)是一個(gè)開(kāi)源的Java框架,是Sun公司推出的一種調用本地方法的技術(shù),是建立在經(jīng)典的JNI基礎之上的一個(gè)框架。之所以說(shuō)它是JNI的替 代者,是因為JNA大大簡(jiǎn)化了調用本地方法的過(guò)程,使用很方便,基本上不需要脫離Java環(huán)境就可以完成。

如果要和上圖做個(gè)比較,那么JNA調用C/C++的過(guò)程大致如下:

可以看到步驟減少了很多,最重要的是我們不需要重寫(xiě)我們的動(dòng)態(tài)鏈接庫文件,而是有直接調用的API,大大簡(jiǎn)化了我們的工作量。

JNA只需要我們寫(xiě)Java代碼而不用寫(xiě)JNI或本地代碼。功能相對于Windows的Platform/Invoke和Python的ctypes。

 

2. JNA技術(shù)原理

JNA使用一個(gè)小型的JNI庫插樁程序來(lái)動(dòng)態(tài)調用本地代碼。開(kāi)發(fā)者使用Java接口描述目標本地庫的功能和結構,這使得它很容易利用本機平臺的功能,而不會(huì )產(chǎn)生多平臺配置和生成JNI代碼的高開(kāi)銷(xiāo)。這樣的性能、準確性和易用性顯然受到很大的重視。

此外,JNA包括一個(gè)已與許多本地函數映射的平臺庫,以及一組簡(jiǎn)化本地訪(fǎng)問(wèn)的公用接口。

 

注意:

JNA是建立在JNI技術(shù)基礎之上的一個(gè)Java類(lèi)庫,它使您可以方便地使用java直接訪(fǎng)問(wèn)動(dòng)態(tài)鏈接庫中的函數。

原來(lái)使用JNI,你必須手工用C寫(xiě)一個(gè)動(dòng)態(tài)鏈接庫,在C語(yǔ)言中映射Java的數據類(lèi)型。

JNA中,它提供了一個(gè)動(dòng)態(tài)的C語(yǔ)言編寫(xiě)的轉發(fā)器,可以自動(dòng)實(shí)現Java和C的數據類(lèi)型映射,你不再需要編寫(xiě)C動(dòng)態(tài)鏈接庫。

也許這也意味著(zhù),使用JNA技術(shù)比使用JNI技術(shù)調用動(dòng)態(tài)鏈接庫會(huì )有些微的性能損失。但總體影響不大,因為JNA也避免了JNI的一些平臺配置的開(kāi)銷(xiāo)。

 

3. JNA簡(jiǎn)單使用

JNA的項目已遷移至Github,目前最新版本是4.1.0,已有打包好的jar文件可供下載。

JNA把一個(gè).dll/.so文件看做是一個(gè)Java接口,下面以一個(gè)簡(jiǎn)單的實(shí)例來(lái)說(shuō)明怎么使用。

當然要從最經(jīng)典的HelloWorld開(kāi)始,我們調用C的printf函數打印出“HelloWorld”(官方的例子),前提是已將jar包加入你的classpath。

package com.sun.jna.examples;import com.sun.jna.Library;import com.sun.jna.Native;import com.sun.jna.Platform;/** Simple example of JNA interface mapping and usage. */public class HelloWorld {    // This is the standard, stable way of mapping, which supports extensive    // customization and mapping of Java to native types.    public interface CLibrary extends Library {        CLibrary INSTANCE = (CLibrary)            Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"),                               CLibrary.class);        void printf(String format, Object... args);    }    public static void main(String[] args) {        CLibrary.INSTANCE.printf("Hello, World\n");        for (int i=0;i < args.length;i++) {            CLibrary.INSTANCE.printf("Argument %d: %s\n", i, args[i]);        }    }}


運行程序,如果沒(méi)有帶參數則只打印出“Hello, World”,如果帶了參數,則會(huì )打印出所有的參數。

很簡(jiǎn)單,不需要寫(xiě)一行C代碼,就可以直接在Java中調用外部動(dòng)態(tài)鏈接庫中的函數!

 

下面來(lái)解釋下這個(gè)程序。

(1)需要定義一個(gè)接口,繼承自Library StdCallLibrary

默認的是繼承Library ,如果動(dòng)態(tài)鏈接庫里的函數是以stdcall方式輸出的,那么就繼承StdCallLibrary,比如眾所周知的kernel32庫。比如上例中的接口定義:

public interface CLibrary extends Library {}

 

(2)接口內部定義

接口內部需要一個(gè)公共靜態(tài)常量:INSTANCE,通過(guò)這個(gè)常量,就可以獲得這個(gè)接口的實(shí)例,從而使用接口的方法,也就是調用外部dll/so的函數。

該常量通過(guò)Native.loadLibrary()這個(gè)API函數獲得,該函數有2個(gè)參數:

  • 第一個(gè)參數是動(dòng)態(tài)鏈接庫dll/so的名稱(chēng),但不帶.dll或.so這樣的后綴,這符合JNI的規范,因為帶了后綴名就不可以跨操作系統平臺了。搜索動(dòng)態(tài)鏈接庫路徑的順序是:先從當前類(lèi)的當前文件夾找,如果沒(méi)有找到,再在工程當前文件夾下面找win32/win64文件夾,找到后搜索對應的dll文件,如果找不到再到WINDOWS下面去搜索,再找不到就會(huì )拋異常了。比如上例中printf函數在Windows平臺下所在的dll庫名稱(chēng)是msvcrt,而在其它平臺如Linux下的so庫名稱(chēng)是c。
  • 第二個(gè)參數是本接口的Class類(lèi)型。JNA通過(guò)這個(gè)Class類(lèi)型,根據指定的.dll/.so文件,動(dòng)態(tài)創(chuàng )建接口的實(shí)例。該實(shí)例由JNA通過(guò)反射自動(dòng)生成。
CLibrary INSTANCE = (CLibrary)            Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"),                               CLibrary.class);

接口中只需要定義你要用到的函數或者公共變量,不需要的可以不定義,如上例只定義printf函數:

void printf(String format, Object... args);

注意參數和返回值的類(lèi)型,應該和鏈接庫中的函數類(lèi)型保持一致。

 

(3)調用鏈接庫中的函數

定義好接口后,就可以使用接口中的函數即相應dll/so中的函數了,前面說(shuō)過(guò)調用方法就是通過(guò)接口中的實(shí)例進(jìn)行調用,非常簡(jiǎn)單,如上例中:

 

CLibrary.INSTANCE.printf("Hello, World\n");        for (int i=0;i < args.length;i++) {            CLibrary.INSTANCE.printf("Argument %d: %s\n", i, args[i]);        }

 

 

 

這就是JNA使用的簡(jiǎn)單例子,可能有人認為這個(gè)例子太簡(jiǎn)單了,因為使用的是系統自帶的動(dòng)態(tài)鏈接庫,應該還給出一個(gè)自己實(shí)現的庫函數例子。其實(shí)我覺(jué)得這個(gè)完全沒(méi)有必要,這也是JNA的方便之處,不像JNI使用用戶(hù)自定義庫時(shí)還得定義一大堆配置信息,對于JNA來(lái)說(shuō),使用用戶(hù)自定義庫與使用系統自帶的庫是完全一樣的方法,不需要額外配置什么信息。比如我在Windows下建立一個(gè)動(dòng)態(tài)庫程序:

#include "stdafx.h"extern "C"_declspec(dllexport) int add(int a, int b);int add(int a, int b) {    return a + b;}


然后編譯成一個(gè)dll文件(比如CDLL.dll),放到當前目錄下,然后編寫(xiě)JNA程序調用即可:

public class DllTest {    public interface CLibrary extends Library {        CLibrary INSTANCE = (CLibrary)Native.loadLibrary("CDLL", CLibrary.class);        int add(int a, int b);    }    public static void main(String[] args) {        int sum = CLibrary.INSTANCE.add(3, 6);        System.out.println(sum);    }}

 

4. JNA技術(shù)難點(diǎn)

有過(guò)跨語(yǔ)言、跨平臺開(kāi)發(fā)的程序員都知道,跨平臺、語(yǔ)言調用的難點(diǎn),就是不同語(yǔ)言之間數據類(lèi)型不一致造成的問(wèn)題。絕大部分跨平臺調用的失敗,都是這個(gè)問(wèn)題造成的。關(guān)于這一點(diǎn),不論何種語(yǔ)言,何種技術(shù)方案,都無(wú)法解決這個(gè)問(wèn)題。JNA也不例外。

上面說(shuō)到接口中使用的函數必須與鏈接庫中的函數原型保持一致,這是JNA甚至所有跨平臺調用的難點(diǎn),因為C/C++的類(lèi)型與Java的類(lèi)型是不一樣的,你必須轉換類(lèi)型讓它們保持一致,比如printf函數在C中的原型為:

void printf(const char *format, [argument]);

你不可能在Java中也這么寫(xiě),Java中是沒(méi)有char *指針類(lèi)型的,因此const char *轉到Java下就是String類(lèi)型了。

這就是類(lèi)型映射(Type Mappings),JNA官方給出的默認類(lèi)型映射表如下:

還有很多其它的類(lèi)型映射,需要的請到JNA官網(wǎng)查看。

另外,JNA還支持類(lèi)型映射定制,比如有的Java中可能找不到對應的類(lèi)型(在Windows API中可能會(huì )有很多類(lèi)型,在Java中找不到其對應的類(lèi)型),JNA中TypeMapper類(lèi)和相關(guān)的接口就提供了這樣的功能。

 

5. JNA能完全替代JNI嗎?

這可能是大家比較關(guān)心的問(wèn)題,但是遺憾的是,JNA是不能完全替代JNI的,因為有些需求還是必須求助于JNI。

使用JNI技術(shù),不僅可以實(shí)現Java訪(fǎng)問(wèn)C函數,也可以實(shí)現C語(yǔ)言調用Java代碼。

而JNA只能實(shí)現Java訪(fǎng)問(wèn)C函數,作為一個(gè)Java框架,自然不能實(shí)現C語(yǔ)言調用Java代碼。此時(shí),你還是需要使用JNI技術(shù)。

JNI是JNA的基礎,是Java和C互操作的技術(shù)基礎。有時(shí)候,你必須回歸到基礎上來(lái)。

 

6.  參考文獻

(1)JNA—JNI終結者

(2)C++DLL編程詳解

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
java調用底層的幾種方法
JNA—JNI終結者
幾種java調用dll的方式
JNA示例
JNA的使用
【轉】如何在android上支持JNA <一>知識準備
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久