久久99久久人婷婷精品综合_超碰aⅴ人人做人人爽欧美_亚洲电影第三页_日韩欧美一中文字暮专区_波多野结衣的一区二区三区_婷婷在线播放_人人视频精品_国产精品日韩精品欧美精品_亚洲免费黄色_欧美性猛交xxxxxxxx

什么是JNI

本篇內(nèi)容主要講解“什么是JNI”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“什么是JNI”吧!

成都創(chuàng)新互聯(lián)公司主營新城網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,app軟件定制開發(fā),新城h5小程序設(shè)計搭建,新城網(wǎng)站營銷推廣歡迎新城等地區(qū)企業(yè)咨詢

首先回顧一下jni的主要功能,從jdk1.1開始jni標準就成為了java平臺的一部分,它提供的一系列的API允許java和其他語言進行交互,實現(xiàn)了在java代碼中調(diào)用其他語言的函數(shù)。通過jni的調(diào)用,能夠?qū)崿F(xiàn)這些功能:

什么是JNI

通常情況下我們一般使用jni用來調(diào)用c或c++中的代碼,在上一篇文章中我們用了下面的流程來描述了native方法的調(diào)用過程:

Java Code -> JNI -> C/C++ Code

但是準確的來說這一過程并不嚴謹,因為最終被執(zhí)行的不是原始的c/c++代碼,而是被編譯連接后的動態(tài)鏈接庫。因此我們將這個過程從單純的代碼調(diào)用層面上進行升級,將jni的調(diào)用過程提高到了jvm和操作系統(tǒng)的層面,來加點細節(jié)進行一下完善:

什么是JNI

看到這里,可能有的小伙伴就要提出疑問了,不是說java語言是跨平臺的嗎,這種與操作系統(tǒng)本地編譯的動態(tài)鏈接庫進行的交互,會不會使java失去跨平臺的可移植性?

針對這一問題,大家可以回想一下以前安裝jdk的經(jīng)歷,在官網(wǎng)的下載列表中提供了各個操作系統(tǒng)的不同版本jdk,例如windowslinuxmac os版本等等,在這些jdk中,針對不同系統(tǒng)有著不同的jvm實現(xiàn)。而java語言的跨平臺性恰好是和它底層的jvm密不可分的,正是依靠不同的操作系統(tǒng)下不同版本jvm的“翻譯”工作,才能使編譯后的字節(jié)碼在不同的平臺下暢通無阻的運行。

在不同操作系統(tǒng)下,c/c++或其他代碼生成的動態(tài)鏈接庫也會有差異,例如在window平臺下會編譯為dll文件,在linux平臺下會編譯為so文件,在mac os下會編譯為jnilib文件。而不同平臺下的jvm,會“約定俗成”的去加載某個固定類型的動態(tài)鏈接庫文件,使得依賴于操作系統(tǒng)的功能可以被正常的調(diào)用,這一過程可以參考下面的圖來進行理解:

什么是JNI

在對jni的整體調(diào)用流程有了一定的了解后,對于它如何調(diào)用其他語言中的函數(shù)這一過程,你是否也會好奇它是怎樣實現(xiàn)的,下面我們就通過手寫一個java程序調(diào)用c++代碼的例子,來理解它的調(diào)用過程。

1、準備java代碼

首先定義一個包含了native方法的類如下,之后我們要使用這個類中的native方法通過jni調(diào)用c++編寫成的動態(tài)鏈接庫中的方法:

public class JniTest {
    static{
        System.loadLibrary("MyNativeDll");
    }

    public static native void callCppMethod();

    public static void main(String[] args) {
        System.out.println("DLL path:"+System.getProperty("java.library.path"));
        callCppMethod();
    }
}

在代碼中主要完成了以下工作:

  • 在靜態(tài)代碼塊中,調(diào)用loadLibrary方法加載本地的動態(tài)鏈接庫,參數(shù)為不包含擴展名的動態(tài)鏈接庫庫文件名。在window平臺下會加載dll文件,在linux平臺下會加載so文件,在mac os下會加載jnilib文件

  • 聲明了一個native方法,native關(guān)鍵字負責通知jvm這里調(diào)用方法的是本地方法,該方法在外部被定義

  • main方法中,打印加載dll文件的路徑,并調(diào)用本地方法

2、生成頭文件

在使用c/c++來實現(xiàn)本地方法時,需要先創(chuàng)建.h頭文件。簡單的來說,c/c++程序通常由頭文件(.h)和定義文件(.c.cpp)組成,頭文件包含了功能函數(shù)、數(shù)據(jù)接口的聲明,而定義文件用于書寫程序的實現(xiàn)。

在jdk8中可以直接使用javac -h指令生成c/c++語言中的頭文件。如果你使用的是較早版本的jdk,需要在執(zhí)行javac編譯完成class文件后,再執(zhí)行javah -jni生成c/c++風格的頭文件(在jdk10的新特性中已經(jīng)刪除了javah這一指令)。我們使用的jdk8簡化了這一步驟,使其可以一步完成,在命令行窗口下執(zhí)行命令:

javac -h ./jni JniTest.java

指令中使用 -h參數(shù)指定放置生成的頭文件的位置,最后的參數(shù)是java源文件的名稱。在這個過程中完成了兩件工作,首先生成class文件,其次在參數(shù)指定的目錄下生成頭文件。生成的頭文件com_cn_jni_JniTest.h內(nèi)容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_cn_jni_JniTest */

#ifndef _Included_com_cn_jni_JniTest
#define _Included_com_cn_jni_JniTest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_cn_jni_JniTest
 * Method:    callCppMethod
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_cn_jni_JniTest_callCppMethod
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

生成的頭文件和大家熟悉的 java接口有些相似,只有函數(shù)的聲明而沒有具體實現(xiàn)。簡單的解釋一下頭文件中的代碼:

  • extern "C"告訴編譯器,這部分代碼使用C語言規(guī)則來進行編譯

  • JNIEXPORTJNICALLjni中定義的兩個宏,使用JNIEXPORT支持在外部程序代碼中調(diào)用該動態(tài)庫中的方法,使用JNICALL定義函數(shù)調(diào)用時參數(shù)的入棧出棧約定

  • 函數(shù)名稱由包名+類名+方法名組成,在該方法中有兩個參數(shù),通過第一個參數(shù)JNIEnv *的對象可以調(diào)用jni.h中封裝好的大量函數(shù) ,第二個參數(shù)代表著native方法的調(diào)用者,當java代碼中定義的native方法是靜態(tài)方法時這里的參數(shù)是jclass,非靜態(tài)方法的參數(shù)是jobject

接下來我們創(chuàng)建一個cpp文件,引用頭文件并實現(xiàn)其中的函數(shù),也就是native方法將要實際執(zhí)行的邏輯:

#include "com_cn_jni_JniTest.h"
#include <stdio.h>
 
JNIEXPORT void JNICALL Java_com_cn_jni_JniTest_callCppMethod
  (JNIEnv *, jclass)
{
    printf("Print From Cpp: \n");
    printf("I am a cpp method ! \n");
}

在方法的實現(xiàn)中加入簡單的printf打印語句,在完成方法的實現(xiàn)后,我們需要將上面的cpp文件編譯為動態(tài)鏈接庫,提供給java中的native方法調(diào)用,因此下面需要在window環(huán)境下安裝gcc環(huán)境。

3、gcc環(huán)境安裝

在window環(huán)境下,如果你不希望為了生成一個dll就去下載體積龐大的的Visual Studio的話,MinGW是一個不錯的選擇,簡單的說它就是一個windows版本下的gcc。那么估計有的同學又要問了,gcc是什么?簡單的來說就是linux系統(tǒng)下C/C++的編譯器,通過它可以將源代碼編譯成可執(zhí)行程序。首先從下面的網(wǎng)址下載mingw-get-setup的安裝程序:

http://sourceforge.net/projects/mingw/  #32位
https://sourceforge.net/projects/mingw-w64/  #64位

需要注意,一定要按照系統(tǒng)位數(shù)安裝對應的版本,否則后面生成的dll在運行時就可能會因位數(shù)不匹配而報錯,我在實驗的過程中第一次就錯誤安裝了32位的MinGw,導致了在程序運行過程中報了下面錯誤:

Exception in thread "main" java.lang.UnsatisfiedLinkError: 
F:\Workspace20\unsafe-test\src\main\java\com\cn\jni\jni\MyNativeDll.dll: 
Can't load IA 32-bit .dll on a AMD 64-bit platform

安裝完成后,將MinGW\bin目錄加入系統(tǒng)環(huán)境變量PATH,輸入下面的指令測試gcc是否可以使用:

gcc -v

如果能夠正常輸出gcc的版本信息,說明gcc安裝成功:

什么是JNI

在測試的過程中發(fā)現(xiàn),如果安裝的是64位的mingw,那么在安裝完成后gcc就已經(jīng)直接可以可用。但是如果安裝的是32位的mingw,需要使用下面的命令單獨安裝gcc

mingw-get install gcc

gcc安裝完成后,如果還想安裝gdbmake等其他指令進行調(diào)試或編譯,同樣可以使用強大的mingw-get命令進行獨立安裝。

4、生成動態(tài)鏈接庫

gcc環(huán)境準備好的條件下,接下來使用下面的命令生成dll動態(tài)鏈接庫:

gcc -m64 -Wl,--add-stdcall-alias -I"D:\Program Files\Java\jdk1.8.0_261\include" 
-I"D:\Program Files\Java\jdk1.8.0_261\include\win32" 
-shared -o MyNativeDll.dll JniTestImpl.cpp

簡單的解釋一下各個參數(shù)的含義:

  • -m64 :將cpp代碼編譯為64位的應用程序

  • -Wl,--add-stdcall-alias-Wl表示將后面的參數(shù)傳遞給連接程序,參數(shù)--add-stdcall-alias表示帶有標準調(diào)用后綴@NN的符號會被剝掉后綴后導出

  • -I:指定頭文件的路徑,在生成的頭文件代碼中引入的jni.h就在這個目錄下

  • -shared:指定生成動態(tài)鏈接庫,如果不使用這個標志那么外部程序?qū)o法連接

  • -o:指定目標的名稱,這里將生成的動態(tài)鏈接庫命名為MyNativeDll.dll

  • JniTestImpl.cpp:被編譯的源程序文件名

在指令的執(zhí)行過程中,都做了什么事呢,可以參考下面這張圖:

什么是JNI

在執(zhí)行過程中,以.cpp源代碼和.h頭文件作為源文件,先進行了預處理、編譯、匯編的操作,圖中省略了這一階段產(chǎn)生的一些中間文件,編譯完成后生成的.o二進制文件相對重要,依賴這個文件,最終生成動態(tài)鏈接庫。

在執(zhí)行了上面的指令后,就會在當前目錄下生成一個MyNativeDll.dll文件,再運行之前準備好的java代碼:

什么是JNI

程序報錯,這是因為在默認的載入庫文件的目錄下沒有找到我們的dll文件。有兩種方式可以解決:

  • 直接將dll文件拷貝到默認的加載目錄下,具體的路徑可以通過System.getProperty("java.library.path")獲取,該方法可能會獲得多個目錄,放在任意一個目錄下即可

  • 是在VM Option中修改啟動參數(shù),指定dll的存放目錄:

-Djava.library.path=F:\Workspace20\unsafe-test\src\main\java\com\cn\jni\jni

再次執(zhí)行,輸出結(jié)果:

DLL path:F:\Workspace20\unsafe-test\src\main\java\com\cn\jni\jni
Print From Cpp: 
I am a cpp method !

可以看到程序加載dll的路徑已經(jīng)切換成了它的存放路徑,并且通過jni調(diào)用成功,輸出了在c++中的代碼邏輯。可以用下面的圖來總結(jié)上面實現(xiàn)jni調(diào)用的過程:

什么是JNI

在對jni的調(diào)用有了一個整體的了解后,如果大家對代理模式比較熟悉的話,也可以從代理模式的角度來理解jni,將jni調(diào)用過程中的各個角色帶入到代理模式中:

  • 代理角色:包含native方法的jni

  • 實現(xiàn)角色:c/c++或其他語言實現(xiàn)的動態(tài)鏈接庫

  • 客戶端:調(diào)用native方法的java類程序

  • 接口(抽象角色):在jni中接口這一角色的存在感相對薄弱,因為jni是跨語言的,所以說無法嚴格的定義一個接口并讓它同時應用于java和其他語言。但是通過生成的.h頭文件,在一定程度上實現(xiàn)了從接口規(guī)范上統(tǒng)一了java中native方法和其他語言中的函數(shù)

以代理模式的概述圖來進行描述:

什么是JNI

上圖在標準代理模式的基礎(chǔ)上做了一些修改以便于理解,因為這里的接口只做規(guī)范約束作用,所以讓客戶端的調(diào)用過程跳過了接口,直接指向了代理角色,再由代理角色調(diào)用實現(xiàn)角色完成功能的調(diào)用。總的來說,jni起到了一個代理或中介的作用,與常見代理不同的是這里只做方法的調(diào)用,而不實現(xiàn)邏輯上的增強。通過這一模式,向java程序員隱藏了底層c/c++代碼的實現(xiàn)細節(jié),讓我們專注于業(yè)務代碼的編寫即可。

到此,相信大家對“什么是JNI”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學習!

當前文章:什么是JNI
轉(zhuǎn)載源于:http://www.js-pz168.com/article16/gojidg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制網(wǎng)站企業(yè)網(wǎng)站制作微信小程序響應式網(wǎng)站Google

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都app開發(fā)公司
久久99久久人婷婷精品综合_超碰aⅴ人人做人人爽欧美_亚洲电影第三页_日韩欧美一中文字暮专区_波多野结衣的一区二区三区_婷婷在线播放_人人视频精品_国产精品日韩精品欧美精品_亚洲免费黄色_欧美性猛交xxxxxxxx
av一区二区三区免费| 正义之心1992免费观看全集完整版| 一本一道久久久a久久久精品91| 欧美日韩国产高清一区二区三区| 久久女同精品一区二区| 亚洲一级片在线观看| 国产美女一区二区三区| 国产亚洲一区二区三区在线播放| 中文字幕一区二区中文字幕 | 午夜电影网亚洲视频| 国产成人啪午夜精品网站男同| 精品国产一区二区三区麻豆免费观看完整版 | 91在线丨porny丨国产| 日产精品久久久一区二区| 丁香婷婷综合网| 欧美国产综合视频| 欧美男人的天堂一二区| 国产精品久久久久一区二区三区| 欧美aⅴ一区二区三区视频| 51精品国产人成在线观看| 在线综合视频网站| 国产亚洲欧美激情| 蜜桃久久av一区| 国产精品乱子乱xxxx| 欧美亚洲动漫精品| 国产精品国产自产拍高清av王其| 极品少妇一区二区三区精品视频| 国产三区精品| 337p亚洲精品色噜噜噜| 一区二区三区影院| av不卡一区二区三区| 一区二区免费在线观看| 国产天堂亚洲国产碰碰| 久久99国产精品麻豆| 久久国产精品 国产精品| 337p亚洲精品色噜噜| 夜夜嗨av一区二区三区中文字幕| 成人精品小蝌蚪| 色婷婷综合久久久中文字幕| 久久精品人人做人人爽97 | 色域天天综合网| 国产精品久久看| 国产精品911| 亚洲一区bb| 亚洲国产精品成人综合色在线婷婷 | 黑人巨大精品欧美一区二区小视频| 在线不卡欧美精品一区二区三区| 一区二区三区四区高清精品免费观看 | 欧美羞羞免费网站| 亚洲欧美日韩中文播放| 99热99精品| 欧美日韩国产一级片| 亚洲国产另类精品专区| 国产精品我不卡| 日韩欧美成人激情| 蜜臀av性久久久久蜜臀aⅴ流畅 | 在线国产亚洲欧美| 一区二区三区中文字幕精品精品| 91麻豆swag| 制服丝袜激情欧洲亚洲| 日韩成人一级大片| 蜜臀久久久久久久| 蜜桃av久久久亚洲精品| 国产日本一区二区| 丁香啪啪综合成人亚洲小说| 日本高清不卡一区| 亚洲小少妇裸体bbw| 国产精品一区二区三区精品 | 一本色道久久99精品综合| |精品福利一区二区三区| a4yy欧美一区二区三区| 欧美精品xxxxbbbb| 日韩黄色片在线观看| 欧美不卡在线一区二区三区| 中文成人av在线| av欧美精品.com| 欧美一区二区免费视频| 久久99久久99小草精品免视看| 亚洲日本精品| 一区二区三区视频在线观看| 国产伦理久久久| 日本一区二区三区四区在线视频| 成人毛片老司机大片| 在线综合+亚洲+欧美中文字幕| 日本美女一区二区| 伊人久久婷婷色综合98网| 一区二区三区日韩欧美| 麻豆传媒一区二区| 国产精品国产三级国产三级人妇| 99在线观看视频| 久久精品免费在线观看| av亚洲精华国产精华精华| 日韩欧美一级二级| 国产suv精品一区二区6| 69堂成人精品免费视频| 国产在线一区二区| 欧美日本高清视频在线观看| 极品少妇xxxx偷拍精品少妇| 欧美亚洲另类激情小说| 美女一区二区视频| 色国产综合视频| 免费人成黄页网站在线一区二区| 一级日韩一区在线观看| 手机精品视频在线观看| 影音先锋欧美资源| 日韩成人免费看| 色www精品视频在线观看| 奇米影视一区二区三区小说| 色婷婷精品久久二区二区蜜臂av| 五月婷婷另类国产| 一本一本久久a久久精品综合麻豆 一本一道波多野结衣一区二区 | 9i看片成人免费高清| 精品国产凹凸成av人导航| 9i在线看片成人免费| 久久精品视频在线看| 国产精品久久久久久久久久直播| 日本一区二区不卡视频| 国产专区一区二区| 亚洲男人的天堂一区二区 | 中文字幕乱码亚洲精品一区| 国产91社区| 亚洲欧美一区二区不卡| 色噜噜狠狠色综合网| 石原莉奈在线亚洲二区| 91福利资源站| 国产一区二区在线影院| 日韩你懂的在线播放| 91小视频免费观看| 中文子幕无线码一区tr | 国产精品天天看| 欧美日产一区二区三区在线观看| 亚洲一区电影777| 色婷婷综合久久久久中文| 激情综合网av| 欧美大度的电影原声| 成人欧美一区二区| 亚洲精品大片www| 一区二区三区三区在线| 狠狠色丁香久久婷婷综合_中| 日韩欧美亚洲一区二区| 91嫩草免费看| 亚洲精品乱码久久久久久 | 国产精品一区二区三区观看| 一区二区在线观看视频在线观看| 制服诱惑一区| 狠狠色丁香久久婷婷综| 亚洲精品一区二区在线观看| 国产伦精品一区二区三区照片| 亚洲一二三四久久| 欧美日韩精品久久久| 99久久久久久| 亚洲欧美日韩小说| 在线精品国精品国产尤物884a| 懂色av中文字幕一区二区三区 | 精品视频全国免费看| 菠萝蜜视频在线观看一区| 国产精品国模大尺度视频| 亚洲欧洲精品一区二区| 国产剧情av麻豆香蕉精品| 国产日韩精品久久久| 亚洲成人av动漫| 国产成人亚洲综合a∨婷婷 | 这里只有精品视频在线观看| av免费精品一区二区三区| 亚洲一区二区五区| 欧美男男青年gay1069videost | 国产性做久久久久久| 色综合久久av| 国产盗摄女厕一区二区三区| 日本一区二区三区电影| 亚洲日本理论电影| 成人高清视频免费观看| 亚洲男人的天堂在线观看| 欧美日韩三级视频| 91欧美一区二区| 午夜精品123| 精品成人一区二区三区四区| 日本免费一区二区三区| 国产激情91久久精品导航 | 99在线视频首页| 日韩中文字幕1| 久久综合九色综合欧美亚洲| 日韩理论片在线观看| 国产成人自拍网| 一区二区视频在线| 欧美一级一级性生活免费录像| 九色综合日本| 国内精品国产成人| 国产精品护士白丝一区av| 欧美吞精做爰啪啪高潮| 高清国产一区| 激情亚洲综合在线| 成人免费小视频| 制服丝袜av成人在线看| 欧美日韩精品免费观看| 成人免费视频网站在线观看| 亚洲一区二区三区激情| 欧美白人最猛性xxxxx69交| 亚洲黄色一区二区三区| 91首页免费视频|