成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java 外部函數(shù)接口:JNI, JNA, JNR

pubdreamcc / 1699人閱讀

摘要:我們知道,發(fā)起函數(shù)調(diào)用,需要構(gòu)造一個(gè)棧幀。構(gòu)造棧幀的具體實(shí)現(xiàn)細(xì)節(jié)的選擇,被稱為調(diào)用慣例。要想完成這個(gè)函數(shù)調(diào)用邏輯,就要運(yùn)行時(shí)構(gòu)造棧幀,生成參數(shù)壓棧和清理堆棧的工作。目前,幾乎支持全部常見的架構(gòu)。

原文:http://nullwy.me/2018/01/java...
如果覺得我的文章對你有用,請隨意贊賞
遇到的問題

前段時(shí)間開發(fā)的時(shí)候,遇到一個(gè)問題,就是如何用 Java 實(shí)現(xiàn) chdir?網(wǎng)上搜索一番,發(fā)現(xiàn)了 JNR-POSIX 項(xiàng)目 [stackoverflow ]。俗話說,好記性不如爛筆頭?,F(xiàn)在將涉及到的相關(guān)知識點(diǎn)總結(jié)成筆記。

其實(shí)針對 Java 實(shí)現(xiàn) chdir 問題,官方 20 多年前就存在對應(yīng)的 bug,即 JDK-4045688 "Add chdir or equivalent notion of changing working directory"。這個(gè) bug 在 1997.04 創(chuàng)建,目前的狀態(tài)是 Won"t Fix(不予解決),理由大致是,若實(shí)現(xiàn)與操作系統(tǒng)一樣的進(jìn)程級別的 chdir,將影響 JVM 上的全部線程,這樣引入了可變(mutable)的全局狀態(tài),這與 Java 的安全性優(yōu)先原則沖突,現(xiàn)在添加全局可變的進(jìn)程狀態(tài),已經(jīng)太遲了,對不變性(immutability)的支持才是 Java 要實(shí)現(xiàn)的特性。

chdir 是平臺相關(guān)的操作系統(tǒng)接口,POSIX 下對應(yīng)的 API 為 int chdir(const char *path);,而 Windows 下對應(yīng)的 API 為 BOOL WINAPI SetCurrentDirectory(_In_ LPCTSTR lpPathName);,另外 Windows 下也可以使用 MSVCRT 中 API 的 int _chdir(const char *dirname);(MSVCRT 下內(nèi)部實(shí)現(xiàn)其實(shí)就是調(diào)用 SetCurrentDirectory [reactos ] )。

Java 設(shè)計(jì)理念是跨平臺,"write once, run anywhere"。很平臺相關(guān)的 API,雖然各個(gè)平臺都有自己的類似的實(shí)現(xiàn),但存在會差異。除了多數(shù)常見功能,Java 并沒有對全部操作系統(tǒng)接口提供完整支持,比如很多 POSIX API。除了 chdir,另外一個(gè)典型的例子是,在 Java 9 以前 JDK 獲取進(jìn)程 id 一直沒有簡潔的方法 [stackoverflow ],最新發(fā)布的 Java 9 中的 JEP 102(Process API Updates)才增強(qiáng)了進(jìn)程 API。獲取進(jìn)程 id 可以使用以下方式 [javadoc ]:

long pid = ProcessHandle.current().pid();

相比其他語言,Pyhon 和 Ruby,對操作系統(tǒng)相關(guān)的接口都有更多的原生支持。Pyhon 和 Ruby 實(shí)現(xiàn)的相關(guān) API 基本上都帶有 POSIX 風(fēng)格。比如上文提到,chdirgetpid,在 Pyhon 和 Ruby 下對應(yīng)的 API 為:Pyhon 的 os 模塊 os.chdir(path) 和 os.getpid();Ruby 的 Dir 類的 [Dir.chdir( [ string] )](https://ruby-doc.org/core-2.2... 類方法和 Process 類的 Process.pid 類屬性。Python 解釋器的 chdir 對應(yīng)源碼為 posixmodule.c#L2611,Ruby 解釋器的 chdir 對應(yīng)源碼為 dir.c#L848 和 win32.c#L6741。

JNI 實(shí)現(xiàn) getpid

Java 下要想實(shí)現(xiàn)本地方法調(diào)用,需要通過 JNI。關(guān)于 JNI 的介紹,可以參閱“Java核心技術(shù),卷II:高級特性,第9版2013”的“第12章 本地方法”,或者讀當(dāng)年 Sun 公司 JNI 設(shè)計(jì)者 Sheng Liang(梁勝)寫的“Java Native Interface: Programmer"s Guide and Specification”。本文只給出實(shí)現(xiàn) getpid 的一個(gè)簡單示例。

首先使用 Maven 創(chuàng)建一個(gè)簡單的腳手架:

mvn archetype:generate     
  -DgroupId=com.test       
  -DartifactId=jni-jnr     
  -DpackageName=com.test   
  -DinteractiveMode=false  

com.test 包下添加 GetPidJni 類:

package com.test;

public class GetPidJni {
    public static native long getpid();

    static {
        System.loadLibrary("getpidjni");
    }

    public static void main(String[] args) {
        System.out.println(getpid());
    }
}

javac 編譯代碼 GetPidJNI.java,然后用 javah 生成 JNI 頭文件:

$ mkdir -p target/classes
$ javac src/main/java/com/test/GetPidJni.java -d "target/classes"
$ javah -cp "target/classes" com.test.GetPidJni

生成的 JNI 頭文件 com_test_GetPidJni.h,內(nèi)容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* Header for class com_test_GetPidJni */

#ifndef _Included_com_test_GetPidJni
#define _Included_com_test_GetPidJni
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_test_GetPidJni
 * Method:    getpid
 * Signature: ()J
 */
JNIEXPORT jlong JNICALL Java_com_test_GetPidJni_getpid
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

現(xiàn)在有了頭文件聲明,但還沒有實(shí)現(xiàn),手動(dòng)敲入 com_test_GetPidJni.c

#include "com_test_GetPidJni.h"

JNIEXPORT jlong JNICALL
Java_com_test_GetPidJni_getpid (JNIEnv * env, jclass c) {
    return getpid();
}

編譯 com_test_GetPidJni.c,生成 libgetpidjni.dylib

$ gcc -I $JAVA_HOME/include -I $JAVA_HOME/include/darwin -dynamiclib -o libgetpidjni.dylib com_test_GetPidJni.c

生成的 libgetpidjni.dylib,就是 GetPidJni.java 代碼中的 System.loadLibrary("getpidjni");,需要加載的 lib。

現(xiàn)在運(yùn)行 GetPidJni 類,就能正確獲取 pid:

$ java -Djava.library.path=`pwd` -cp "target/classes" com.test.GetPidJni

JNI 的問題是,膠水代碼(黏合 Java 和 C 庫的代碼)需要程序員手動(dòng)書寫,對不熟悉 C/C++ 的同學(xué)是很大的挑戰(zhàn)。

JNA 實(shí)現(xiàn) getpid

JNA(Java Native Access, wiki, github, javadoc, mvn),提供了相對 JNI 更加簡潔的調(diào)用本地方法的方式。除了 Java 代碼外,不再需要額外的膠水代碼。這個(gè)項(xiàng)目最早可以追溯到 Sun 公司 JNI 設(shè)計(jì)者 Sheng Liang 在 1999 年 JavaOne 上的分享。2006 年 11月,Todd Fast (也來自 Sun 公司) 首次將 JNA 發(fā)布到 dev.java.net 上。Todd Fast 在發(fā)布時(shí)提到,自己在這個(gè)項(xiàng)目上已經(jīng)斷斷續(xù)續(xù)開發(fā)并完善了 6-7 年時(shí)間,項(xiàng)目剛剛在 JDK 5 上重構(gòu)和重設(shè)計(jì)過,還可能有很多缺陷或缺點(diǎn),希望其他人能瀏覽代碼并參與進(jìn)來。Timothy Wall 在 2007 年 2 月重啟了這項(xiàng)目,引入了很多重要功能,添加了 Linux 和 OSX 支持(原本只在 Win32 上測試過),加強(qiáng)了 lib 的可用性(而非僅僅基本功能可用) [ref ]。

看下示例代碼:

import com.sun.jna.Library;
import com.sun.jna.Native;

public class GetPidJNA {

    public interface LibC extends Library {
        long getpid();
    }

    public static void main(String[] args) {
        LibC libc = Native.loadLibrary("c", LibC.class);
        System.out.println(libc.getpid());
    }
}
JNR 實(shí)現(xiàn) getpid

最初,JRuby 的核心開發(fā)者 Charles Nutter 在實(shí)現(xiàn) Ruby 的 POSIX 集成時(shí)就使用了 JNA [ref ]。但過了一段時(shí)候后,開始開發(fā) JNR(Java Native Runtime, github, mvn) 替代 JNA。Charles Nutter 在介紹 JNR 的 slides 中闡述了原因:

Why Not JNA?
- Preprocessor constants?
- Standard API sets out of the box
- C callbacks?
- Performance?!?

即,(1) 預(yù)處理器的常量支持(通過 jnr-constants 解決);(2) 開箱即用的標(biāo)準(zhǔn) API(作者實(shí)現(xiàn)了 jnr-posix, jnr-x86asm, jnr-enxio, jnr-unixsocket);(3) C 回調(diào) callback 支持;(4) 性能(提升 8-10 倍)。

使用 JNR-FFI(github, mvn)實(shí)現(xiàn) getpid,示例代碼:

import jnr.ffi.LibraryLoader;

public class GetPidJnr {

    public interface LibC {
        long getpid();
    }

    public static void main(String[] args) {
        LibC libc = LibraryLoader.create(LibC.class).load("c");
        System.out.println(libc.getpid());
    }
}

使用 JNR-POSIX(github, mvn)實(shí)現(xiàn) chdirgetpid,示例代碼:

import jnr.posix.POSIX;
import jnr.posix.POSIXFactory;

public class GetPidJnrPosix {

    private static POSIX posix = POSIXFactory.getPOSIX();

    public static void main(String[] args) {
        System.out.println(posix.getcwd());
        posix.chdir("..");
        System.out.println(posix.getcwd());
        System.out.println(posix.getpid());
    }
}
JMH 性能比較

性能測試代碼為 BenchmarkFFI.java(github),測試結(jié)果如下:

# JMH version: 1.19
# VM version: JDK 1.8.0_144, VM 25.144-b01

Benchmark                          Mode  Cnt      Score      Error   Units
BenchmarkFFI.testGetPidJna        thrpt   10   8225.209 ±  206.829  ops/ms
BenchmarkFFI.testGetPidJnaDirect  thrpt   10  10257.505 ±  736.135  ops/ms
BenchmarkFFI.testGetPidJni        thrpt   10  77852.899 ± 3167.101  ops/ms
BenchmarkFFI.testGetPidJnr        thrpt   10  58261.657 ± 5187.550  ops/ms

即:JNI > JNR > JNA (Direct Mapping) > JNA (Interface Mapping)。相對 JNI 的實(shí)現(xiàn)性能,其他三種方式,從大到小的性能百分比依次為:74.8% (JNR), 13.2% (JnaDirect), 10.6% (JNA)。在博主電腦上測試,JNR 相比 JNA 將近快了 6-7 倍(JNR 作者 Charles Nutter 針對 getpid 的測試結(jié)果是 JNR 比 JNA 快 8-10 倍 [twitter slides ])。

實(shí)現(xiàn)原理 JNA 源碼簡析

先來看下 JNA,JNA 官方文檔 FunctionalDescription.md,對其實(shí)現(xiàn)原理有很好的闡述。這里將從源碼角度分析實(shí)現(xiàn)的核心邏輯。

回顧下代碼,我們現(xiàn)實(shí)定義了接口 LibC,然后通過 Native.loadLibrary("c", LibC.class) 獲取了接口實(shí)現(xiàn)。這一步是怎么做到的呢?翻下源碼 Native.java#L547 就知道,其實(shí)是通過動(dòng)態(tài)代理(dynamic proxy)實(shí)現(xiàn)的。使用動(dòng)態(tài)代理需要實(shí)現(xiàn) InvocationHandler 接口,這個(gè)接口的實(shí)現(xiàn)在 JNA 源碼中是類 com.sun.jna.Library.Handler。示例中的 LibC 接口定義的全部方法,將全部分派到 Handler 的 invoke 方法下。

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;

然后根據(jù)返回參數(shù)的不同,分派到 Native 類的,invokeXxx 本地方法:

/**
 * Call the native function.
 *
 * @param function  Present to prevent the GC to collect the Function object
 *                  prematurely
 * @param fp        function pointer
 * @param callFlags calling convention to be used
 * @param args      Arguments to pass to the native function
 *
 * @return The value returned by the target native function
 */
static native int invokeInt(Function function, long fp, int callFlags, Object[] args);

static native long invokeLong(Function function, long fp, int callFlags, Object[] args);

static native Object invokeObject(Function function, long fp, int callFlags, Object[] args);
...

比如,long getpid() 會被分派到 invokeLong,而 int chmod(String filename, int mode) 會被分派到 invokeInt。invokeXxx 本地方法參數(shù):

參數(shù) Function function,記錄了 lib 信息、函數(shù)名稱、函數(shù)指針地址、調(diào)用慣例等元信息;

參數(shù) long fp,即函數(shù)指針地址,函數(shù)指針地址通過 Native#findSymbol()獲得(底層是 Linux API dlsym 或 Windows API GetProcAddress )。

參數(shù) int callFlags,即調(diào)用約定,對應(yīng) cdecl 或 stdcall。

參數(shù) int callFlags,即函數(shù)入?yún)?,若無參數(shù),args 大小為 0,若有多個(gè)參數(shù),原本的入?yún)⒈粡淖蟮接乙来伪4娴?args 數(shù)組中。

再來看下 invokeXxx 本地方法的實(shí)現(xiàn) dispatch.c#L2122(invokeIntinvokeLong 實(shí)現(xiàn)源碼類似):

/*
 * Class:     com_sun_jna_Native
 * Method:    invokeInt
 * Signature: (Lcom/sun/jna/Function;JI[Ljava/lang/Object;)I
 */
JNIEXPORT jint JNICALL
Java_com_sun_jna_Native_invokeInt(JNIEnv *env, jclass UNUSED(cls), 
                                  jobject UNUSED(function), jlong fp, jint callconv,
                                  jobjectArray arr)
{
    ffi_arg result;
    dispatch(env, L2A(fp), callconv, arr, &ffi_type_sint32, &result);
    return (jint)result;
}

即,全部 invokeXxx 本地方法統(tǒng)一被分派到 dispatch 函數(shù) dispatch.c#L439:

static void
dispatch(JNIEnv *env, void* func, jint flags, jobjectArray args,
ffi_type *return_type, void *presult)

這個(gè) dispatch 函數(shù)是全部邏輯的核心,實(shí)現(xiàn)最終的本地函數(shù)調(diào)用。

我們知道,發(fā)起函數(shù)調(diào)用,需要構(gòu)造一個(gè)棧幀(stack frame)。構(gòu)造棧幀,涉及到參數(shù)壓棧次序(參數(shù)從左到右壓入還是從右到左壓入)和清理?xiàng)ㄕ{(diào)用者清理還是被調(diào)用者清理)等實(shí)現(xiàn)細(xì)節(jié)問題。不同的編譯器在不同的 CPU 架構(gòu)下有不同的選擇。構(gòu)造棧幀的具體實(shí)現(xiàn)細(xì)節(jié)的選擇,被稱為調(diào)用慣例(calling convention)。按照調(diào)用慣例構(gòu)造整個(gè)棧幀,這個(gè)過程由編譯器在編譯階段完成的。比如要想發(fā)起 sum(2, 3) 這個(gè)函數(shù)調(diào)用,編譯器可能會生成如下等價(jià)匯編代碼:

; 調(diào)用者清理堆棧(caller clean-up),參數(shù)從右到左壓入棧
push 3
push 2
call _sum      ; 將返回地址壓入棧, 同時(shí) sum 的地址裝入 eip
add  esp, 8    ; 清理堆棧, 兩個(gè)參數(shù)占用 8 字節(jié)

dispatch 函數(shù)是,需要調(diào)用的函數(shù)指針地址、輸入?yún)?shù)和返回參數(shù),全部是運(yùn)行時(shí)確定。要想完成這個(gè)函數(shù)調(diào)用邏輯,就要運(yùn)行時(shí)構(gòu)造棧幀,生成參數(shù)壓棧和清理堆棧的工作。JNA 3.0 之前,實(shí)現(xiàn)運(yùn)行時(shí)構(gòu)造棧幀的邏輯的對應(yīng)代碼 dispatch_i386.c、dispatch_ppc.c 和 dispatch_sparc.s,分別實(shí)現(xiàn) Intel x86、PowerPC 和 Sparc 三種 CPU 架構(gòu)。

運(yùn)行時(shí)函數(shù)調(diào)用,這個(gè)問題其實(shí)是一個(gè)一般性的通用問題。早在 1996 年 10 月,Cygnus Solutions 的工程師 Anthony Green 等人就開發(fā)了 libffi(home, wiki, github, doc),解決的正是這個(gè)問題。目前,libffi 幾乎支持全部常見的 CPU 架構(gòu)。于是,從 JNA 3.0 開始,摒棄了原先手動(dòng)構(gòu)造棧幀的做法,把 libffi 集成進(jìn)了 JNA。

直接映射(Direct Mapping)
https://docs.oracle.com/javas...
http://www.chiark.greenend.or...

JNR 源碼簡析

JNR 底層同樣也是依賴 libffi,參見 jffi。但 JNR 相比 JNA 性能更好,做了很有優(yōu)化。比較重要的點(diǎn)是,JNA 使用動(dòng)態(tài)代理生成實(shí)現(xiàn)類,而 JNR 使用 ASM 字節(jié)碼操作庫生成直接實(shí)現(xiàn)類,去除了每次調(diào)用本地方法時(shí)額外的動(dòng)態(tài)代理的邏輯。使用 ASM 生成實(shí)現(xiàn)類,對應(yīng)的代碼為 AsmLibraryLoader.java。其他細(xì)節(jié),限于文檔不全,本人精力有限,不再展開。

Java 9 的 getpid 實(shí)現(xiàn)

Java 9 以前 JDK 獲取進(jìn)程 id 沒有簡潔的方法,最新發(fā)布的 Java 9 中的 JEP 102(Process API Updates)增強(qiáng)了進(jìn)程 API。進(jìn)程 id 可以使用以下方式 [javadoc ]

long pid = ProcessHandle.current().pid();

翻閱實(shí)現(xiàn)源碼,可以看到對應(yīng)的實(shí)現(xiàn)就是 JNI 調(diào)用:

jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl [src ]

/**
* Return the pid of the current process.
*
* @return the pid of the  current process
*/
private static native long getCurrentPid0();

*nix 平臺下實(shí)現(xiàn)為:

jdk/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c [src ]

/*
 * Class:     java_lang_ProcessHandleImpl
 * Method:    getCurrentPid0
 * Signature: ()J
 */
JNIEXPORT jlong JNICALL
Java_java_lang_ProcessHandleImpl_getCurrentPid0(JNIEnv *env, jclass clazz) {
    pid_t pid = getpid();
    return (jlong) pid;
}

Windows 平臺下實(shí)現(xiàn)為:

jdk/src/java.base/windows/native/libjava/ProcessHandleImpl_win.c [src ]

/*
 * Returns the pid of the caller.
 *
 * Class:     java_lang_ProcessHandleImpl
 * Method:    getCurrentPid0
 * Signature: ()J
 */
JNIEXPORT jlong JNICALL
Java_java_lang_ProcessHandleImpl_getCurrentPid0(JNIEnv *env, jclass clazz) {
    DWORD  pid = GetCurrentProcessId();
    return (jlong)pid;
}
參考資料

Changing the current working directory in Java? https://stackoverflow.com/q/8...

How can a Java program get its own process ID? http://stackoverflow.com/q/35842

Java核心技術(shù),卷II:高級特性,第9版2013:第12章 本地方法,豆瓣

Java Native Interface: Programmer"s Guide and Specification, Sheng Liang (wiki,linkedin,msa), 1999,豆瓣:作者梁勝,中國科技大學(xué)少年班83級,并擁有耶魯大學(xué)計(jì)算機(jī)博士學(xué)位(1990-1996),目前 Rancher Labs 創(chuàng)始人兼 CEO [ref ]

2013-07 Charles Nutter: Java Native Runtime http://www.oracle.com/technet...

JEP 191: Foreign Function Interface http://openjdk.java.net/jeps/191 作者是Charles Nutter

2014-03 Java 外部函數(shù)接口 http://www.infoq.com/cn/news/...

2005-08 Brian Goetz:用動(dòng)態(tài)代理進(jìn)行修飾 https://www.ibm.com/developer...

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/71846.html

相關(guān)文章

  • java如何獲取hdd序列號

    摘要:序在里頭如何獲取硬盤的序列號呢,這里涉及了跨平臺的問題,不同的操作系統(tǒng)的查看命令不一樣,那么里頭如何去適配呢。這里使用了這個(gè)項(xiàng)目來獲取。使用的是的方式而不是的形式來進(jìn)行本地調(diào)用的。獲取方法,,,和之間的區(qū)別是什么,它們的調(diào)用效率怎么排名 序 在java里頭如何獲取硬盤的序列號呢,這里涉及了跨平臺的問題,不同的操作系統(tǒng)的查看命令不一樣,那么java里頭如何去適配呢。這里使用了oshi這個(gè)...

    jzman 評論0 收藏0
  • 一個(gè)簡單的JNA使用例子

    摘要:提供了這個(gè)技術(shù)來實(shí)現(xiàn)調(diào)用和程序,但實(shí)現(xiàn)起來比較麻煩,所以后來公司在的基礎(chǔ)上實(shí)現(xiàn)了一個(gè)框架使用這個(gè)框架可以減輕程序員的負(fù)擔(dān),使得調(diào)用和容易很多。 使用JAVA語言開發(fā)程序比較高效,但有時(shí)對于一些性能要求高的系統(tǒng),核心功能可能是用C或者C++語言編寫的,這時(shí)需要用到JAVA的跨語言調(diào)用功能。JAVA提供了JNI這個(gè)技術(shù)來實(shí)現(xiàn)調(diào)用C和C++程序,但JNI實(shí)現(xiàn)起來比較麻煩,所以后來SUN公司在...

    winterdawn 評論0 收藏0
  • 在運(yùn)行期通過反射了解JVM內(nèi)部機(jī)制

    摘要:我們找到了許多有趣的工具和組件用來檢測狀態(tài)的各個(gè)方面,其中一個(gè)就是在運(yùn)行期通過反射了解內(nèi)部機(jī)制。由于包含多種的實(shí)現(xiàn),就是供具體實(shí)現(xiàn)比如必須繼承的抽象類。調(diào)試器框架是可擴(kuò)展的,這意味著可以通過繼承這個(gè)抽象類來使用另一個(gè)調(diào)試器。 在日常工作中,我們都習(xí)慣直接使用或者通過框架使用反射。在沒有反射相關(guān)硬編碼知識的情況下,這是Java和Scala編程中使用的類庫與我們的代碼之間進(jìn)行交互的一種主要...

    crossea 評論0 收藏0
  • Java調(diào)用dll文件

    摘要:目錄創(chuàng)建創(chuàng)建項(xiàng)目與工具項(xiàng)目與工具步驟與代碼步驟與代碼使用調(diào)用使用調(diào)用項(xiàng)目與工具項(xiàng)目與工具步驟與代碼步驟與代碼實(shí)際效果實(shí)際效果參考鏈接參考鏈接創(chuàng)建項(xiàng)目與工具步驟與代碼使用創(chuàng)建動(dòng)態(tài)鏈接庫項(xiàng)目設(shè)置項(xiàng)目名與項(xiàng)目 目錄 1 C++創(chuàng)建dll 1.1 項(xiàng)目與工具 1.2 步驟與代碼 2 Java使用JN...

    Jeff 評論0 收藏0
  • Head First JNA

    摘要:與動(dòng)態(tài)鏈接庫配套的,會有相應(yīng)的頭文件,來聲明動(dòng)態(tài)鏈接庫中對外暴露的方法。結(jié)構(gòu)體映射結(jié)構(gòu)體映射類編寫類,繼承,表示這個(gè)一個(gè)結(jié)構(gòu)體。聲明字段與,并且設(shè)置訪問屬性為。計(jì)算機(jī)狀態(tài)結(jié)構(gòu)體結(jié)構(gòu)體指針結(jié)構(gòu)體具體的值至此,功能完成。 問題描述 虛擬化項(xiàng)目,需要用到Java調(diào)用原生代碼的技術(shù),我們使用的是開源庫JNA(Java Native Access)。 Native(C/C++)代碼,編譯生成動(dòng)態(tài)...

    YPHP 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<