黄色网页视频 I 影音先锋日日狠狠久久 I 秋霞午夜毛片 I 秋霞一二三区 I 国产成人片无码视频 I 国产 精品 自在自线 I av免费观看网站 I 日本精品久久久久中文字幕5 I 91看视频 I 看全色黄大色黄女片18 I 精品不卡一区 I 亚洲最新精品 I 欧美 激情 在线 I 人妻少妇精品久久 I 国产99视频精品免费专区 I 欧美影院 I 欧美精品在欧美一区二区少妇 I av大片网站 I 国产精品黄色片 I 888久久 I 狠狠干最新 I 看看黄色一级片 I 黄色精品久久 I 三级av在线 I 69色综合 I 国产日韩欧美91 I 亚洲精品偷拍 I 激情小说亚洲图片 I 久久国产视频精品 I 国产综合精品一区二区三区 I 色婷婷国产 I 最新成人av在线 I 国产私拍精品 I 日韩成人影音 I 日日夜夜天天综合

如何用JNI技術(shù)提高Java的性能詳解

系統(tǒng) 2198 0

?阻礙Java獲得廣泛應(yīng)用的一個(gè)主要因素是Java程序的運(yùn)行效率。Java是介于解釋型和編譯型之間的一種語(yǔ)言,同樣的程序,如果用編譯型語(yǔ)言C來(lái)實(shí)現(xiàn),其運(yùn)行速度一般要比Java快一倍以上。Java具有平臺(tái)無(wú)關(guān)性,這使人們?cè)陂_(kāi)發(fā)企業(yè)級(jí)應(yīng)用的時(shí)候總是把它作為主要候選方案之一,但是性能方面的因素又大大削弱了它的競(jìng)爭(zhēng)力。為此,提高Java的性能就顯得十分重要。

? 問(wèn)題的提出

????? Sun公司及Java的支持者們?yōu)樘岣逬ava的運(yùn)行速度已經(jīng)做出了許多努力,其中大多數(shù)集中在程序設(shè)計(jì)的方法和模式選擇方面。由于算法和設(shè)計(jì)模式的優(yōu)化是通用的,對(duì)Java有效的優(yōu)化算法和設(shè)計(jì)模式,對(duì)其他編譯語(yǔ)言也基本同樣適用,因此不能從根本上改變Java程序與編譯型語(yǔ)言在執(zhí)行效率方面的差異。

JIT(Just In Time,及時(shí)編譯)技術(shù)是個(gè)比較好的思想。它的基本原理是:首先通過(guò)Java編譯器把Java源代碼編譯成平臺(tái)無(wú)關(guān)的二進(jìn)制字節(jié)碼。然后在Java程序真正執(zhí)行之前,系統(tǒng)通過(guò)JIT編譯器把Java的字節(jié)碼編譯為本地化機(jī)器碼。最后,系統(tǒng)執(zhí)行本地化機(jī)器碼,節(jié)省了對(duì)字節(jié)碼進(jìn)行解釋的時(shí)間。這樣做的優(yōu)點(diǎn)是大大提高了Java程序的性能,縮短了加載程序的時(shí)間;同時(shí),由于編譯的結(jié)果并不在程序運(yùn)行間保存,因此也節(jié)約了存儲(chǔ)空間。缺點(diǎn)是由于JIT編譯器對(duì)所有的代碼都想優(yōu)化,因此同樣也占用了很多時(shí)間。

動(dòng)態(tài)優(yōu)化技術(shù)是提高Java性能的另一個(gè)嘗試。該技術(shù)試圖通過(guò)把Java源程序直接編譯成機(jī)器碼,以充分利用Java動(dòng)態(tài)編譯和靜態(tài)編譯技術(shù)來(lái)提高Java的性能。該方法把輸入的Java源碼或字節(jié)碼轉(zhuǎn)換為經(jīng)過(guò)高度優(yōu)化的可執(zhí)行代碼和動(dòng)態(tài)庫(kù) (Windows中的. dll文件或Unix中的. so文件)。該技術(shù)能大大提高程序的性能,但卻破壞了Java的可移植性。

JNI技術(shù)

實(shí)際上,有一種通常為我們忽視的技術(shù)可以在很大程度上解決這個(gè)難題,那就是JNI(Java Native Interface, Java本地化方法)。主張采用純Java的人們通常反對(duì)本地化代碼的使用,他們認(rèn)為在Java程序執(zhí)行的過(guò)程中調(diào)用C/C++程序會(huì)影響程序的可移植性和安全性。還有一些人認(rèn)為JNI只是對(duì)過(guò)去混合編程技術(shù)的簡(jiǎn)單擴(kuò)展,其實(shí)際目的是為了充分利用大量原有的C程序庫(kù)。

其實(shí),我們不必拘泥于嚴(yán)格的平臺(tái)獨(dú)立性限制,因?yàn)椴捎肑NI技術(shù)只是針對(duì)一些嚴(yán)重影響Java性能的代碼段,該部分可能只占源程序的極少部分,所以幾乎可以不考慮該部分代碼在主流平臺(tái)之間移植的工作量。同時(shí),也不必過(guò)分擔(dān)心類型匹配問(wèn)題,我們完全可以控制代碼不出現(xiàn)這種錯(cuò)誤。此外,也不必?fù)?dān)心安全控制問(wèn)題,因?yàn)镴ava安全模型已擴(kuò)展為允許非系統(tǒng)類加載和調(diào)用本地方法。根據(jù)Java規(guī)范,從JDK 1. 2開(kāi)始,F(xiàn)indClass將設(shè)法找到與當(dāng)前的本地方法關(guān)聯(lián)的類加載器。如果平臺(tái)相關(guān)代碼屬于一個(gè)系統(tǒng)類,則無(wú)需涉及任何類加載器; 否則,將調(diào)用適當(dāng)?shù)念惣虞d器來(lái)加載和鏈接已命名的類。換句話說(shuō),如果在Java程序中直接調(diào)用C/C++語(yǔ)言產(chǎn)生的機(jī)器碼,該部分代碼的安全性就由Java虛擬機(jī)控制。

JNI實(shí)現(xiàn)步驟

編寫(xiě)JNI代碼的大致流程如下圖所示:

JNI實(shí)現(xiàn)流程圖

JNI實(shí)現(xiàn)流程圖

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

//Compute.java

……

public class Compute {

public native double comp (double [] params);

……

static {

// 調(diào)用動(dòng)態(tài)鏈接庫(kù)

System. loadLibrary(“mathlib”);

}

……

}

2. 將該類源文件用Java類編譯器編譯成二進(jìn)制字節(jié)碼文件。由于采用了native關(guān)鍵字聲明,編譯器會(huì)忽視沒(méi)有代碼體的JNI方法部分。

3. 利用javah -jni *.class 生成相關(guān)JNI方法的頭文件。我們可以手工生成該文件,但是由于Java虛擬機(jī)是根據(jù)一定的命名規(guī)范完成對(duì)JNI方法的調(diào)用,所以手工編寫(xiě)頭文件需要特別小心。

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

//Compute. h

……

extern “C” {

JNIEXPORT jdouble JNICALL Java_Compute_comp (JNIEnv *, 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. 根據(jù)頭文件編寫(xiě)相應(yīng)方法的實(shí)現(xiàn)代碼。由于篇幅所限,具體的實(shí)現(xiàn)部分在此不再贅述。在編碼過(guò)程中,需要注意變量的長(zhǎng)度問(wèn)題,例如Java的整型變量長(zhǎng)度為32位,而C語(yǔ)言為16位,所以要仔細(xì)核對(duì)變量類型映射表,防止在傳值過(guò)程中出現(xiàn)問(wèn)題。

5. 利用C/C++編譯器將JNI實(shí)現(xiàn)代碼編譯成動(dòng)態(tài)鏈接庫(kù)。調(diào)用者類中需要顯式調(diào)用該鏈接庫(kù)。

在Win32環(huán)境下,可以利用Visual C ++或其他能產(chǎn)生DLL文件的C/C++編譯器將實(shí)現(xiàn)代碼編譯成動(dòng)態(tài)鏈接庫(kù)。筆者利用的是Microsoft.NET Framework的編譯器。編譯指令如下,其中%Java_HOME%是筆者的jdk安裝目錄變量:

cl -I%Java_HOME%\include

-I%Java_HOME%\include\win32

-LD jnicomp. c -Femathlib. dll

在Sun Soloaris下,相應(yīng)指令為:

cc -G -I/usr/local/java/include -I/usr/local/java/include/solaris jnicomp. c \

-o mathlib. so

注意,編譯的時(shí)候需要用I指令包含必要的庫(kù)文件路徑。

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

JNI技術(shù)的應(yīng)用

一些主要的Java技術(shù),如JDBC和RMI,大部分都采用JNI方式實(shí)現(xiàn)。但是,采用JNI確實(shí)會(huì)影響程序的平臺(tái)無(wú)關(guān)性,所以只能在特別需要的地方才能使用。通常來(lái)說(shuō),如果遇到下面的情況,我們可以考慮JNI:

● 需要直接操作物理設(shè)備,而沒(méi)有相關(guān)的驅(qū)動(dòng)程序,這時(shí)候我們可能需要用C甚至匯編語(yǔ)言來(lái)編寫(xiě)該設(shè)備的驅(qū)動(dòng),然后通過(guò)JNI調(diào)用;

● 涉及大量數(shù)學(xué)運(yùn)算的部分,用Java會(huì)帶來(lái)些效率上的損失;

● 用Java會(huì)產(chǎn)生系統(tǒng)難以支付的開(kāi)銷,如需要大量網(wǎng)絡(luò)鏈接的場(chǎng)合;

● 存在大量可重用的C/C++代碼,通過(guò)JNI可以減少開(kāi)發(fā)工作量,避免重復(fù)開(kāi)發(fā)。

另外,在利用JNI技術(shù)的時(shí)候要注意以下幾點(diǎn):

● 由于Java安全機(jī)制的限制,不要試圖通過(guò)Jar文件的方式發(fā)布包含本地化方法的Applet到客戶端;

● 注意內(nèi)存管理問(wèn)題,雖然在本地方法返回 Java 后將自動(dòng)釋放局部引用,但過(guò)多的局部引用將使虛擬機(jī)在執(zhí)行本地方法時(shí)耗盡內(nèi)存;

● JNI技術(shù)不僅可以讓Java程序調(diào)用C/C++代碼,也可以讓C/C++代碼調(diào)用Java代碼。


如何用JNI技術(shù)提高Java的性能詳解


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論