Java中一個(gè)強(qiáng)大到你難以置信的功能驹饺,逐漸被遺忘钳枕?

說(shuō)起Java,簡(jiǎn)單好用赏壹,但是Java中很多非常強(qiáng)大的技術(shù)卻逐漸被遺忘了~~

在Java語(yǔ)言出現(xiàn)之前鱼炒,很多系統(tǒng)都是使用C和C++開(kāi)發(fā)的。Java出現(xiàn)之后蝌借,由于其面向?qū)ο蟮乃枷敫臃先藗兊乃季S習(xí)慣昔瞧,Java也不用像C和C++那樣需要程序員手動(dòng)管理內(nèi)存的分配和回收。說(shuō)白了菩佑,就是簡(jiǎn)單好用自晰。由于Java的諸多優(yōu)點(diǎn),使其一躍霸榜編程語(yǔ)言前排很多年稍坯。

為了能夠和使用C和C++寫(xiě)的程序進(jìn)行交互酬荞,Java提供了本地方法的特性,也就是我們常說(shuō)的JNI技術(shù)瞧哟,然而混巧,隨著互聯(lián)網(wǎng)的高速發(fā)展,分布式勤揩、微服務(wù)咧党、大數(shù)據(jù)、云計(jì)算等技術(shù)和框架層出不窮雄可,但大多數(shù)框架采用單一的語(yǔ)言所開(kāi)發(fā)凿傅。JNI這項(xiàng)Java中提供的強(qiáng)大功能,卻逐漸的被人遺忘了数苫。

為何使用JNI

最近聪舒,在分析500多TB的數(shù)據(jù),從500多TB的數(shù)據(jù)中分析用戶(hù)的行為習(xí)慣虐急,以便為用戶(hù)提供更好的產(chǎn)品體驗(yàn)和推薦更加適合用戶(hù)的產(chǎn)品箱残。然而,在實(shí)現(xiàn)算法的過(guò)程中,使用Java語(yǔ)言開(kāi)發(fā)的算法從500多TB的數(shù)據(jù)中被辑,單獨(dú)分析某個(gè)用戶(hù)某段時(shí)間的行為時(shí)燎悍,耗費(fèi)了極大的時(shí)間開(kāi)銷(xiāo)。無(wú)論如何優(yōu)化算法盼理,都不能達(dá)到預(yù)期的效果谈山。很顯然,這不符合性能要求宏怔。

一名小伙伴對(duì)我說(shuō):試試C語(yǔ)言嘛奏路。對(duì)啊臊诊!我為啥不試試用C語(yǔ)言寫(xiě)算法啊鸽粉,于是乎,使用C語(yǔ)言寫(xiě)了算法抓艳,經(jīng)過(guò)不斷的優(yōu)化和調(diào)整触机,算是初步達(dá)到了算法性能要求。但是向數(shù)據(jù)大屏展示數(shù)據(jù)的時(shí)候玷或,后端還是要以微服務(wù)的形式部署儡首,于是我想到了Java中的JNI技術(shù)

注:后面單獨(dú)寫(xiě)一篇我是如何分析500多TB數(shù)據(jù)的。

如何使用JNI

先說(shuō)說(shuō)使用JNI時(shí)有哪些坑吧庐椒,以避免小伙伴們重復(fù)踩坑椒舵,這里蚂踊,大家需要注意的是:在使用JNI技術(shù)調(diào)用dll動(dòng)態(tài)鏈接庫(kù)時(shí)约谈,32位dll只能是32位JDK去調(diào)用,64位dll只能是64位JDK去調(diào)用犁钟。這個(gè)必須是這樣的棱诱,如果發(fā)現(xiàn)無(wú)法調(diào)用或者提示版本錯(cuò)誤,首先要檢查下JDK的位數(shù)和dll的位數(shù)是否是對(duì)應(yīng)的涝动。

為了能夠讓小伙伴們順利的按照文章開(kāi)發(fā)出自己的JNI程序迈勋,這里,我就詳細(xì)的說(shuō)下如何開(kāi)發(fā)一個(gè)JNI程序醋粟,主要分三個(gè)大的方面來(lái)說(shuō)明如何使用JNI技術(shù)調(diào)用C和C++寫(xiě)的程序靡菇。

注意:本文中使用的是jna Java類(lèi)庫(kù)實(shí)現(xiàn)JNI開(kāi)發(fā)。

開(kāi)發(fā)dll動(dòng)態(tài)鏈接庫(kù)

下載VS

小伙伴們可以在【冰河技術(shù)】公眾號(hào)回復(fù)“vscode”米愿,獲取VS2010下載鏈接厦凤。

使用VS開(kāi)發(fā)dll

VS新建項(xiàng)目

輸入項(xiàng)目名稱(chēng)

選擇空項(xiàng)目,點(diǎn)擊完成

創(chuàng)建完成后育苟,將下面這段代碼復(fù)制進(jìn)去:

 class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="c++" cid="n32" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">#include <windows.h> 
#include <iostream>
#include <string>
using std::string;
using std::cin;
using std::cout;
using std::endl; 

#define MYLIBAPI extern "C" __declspec( dllexport ) 

//這的參數(shù)是必須的较鼓,也可以定義為.c頭文件
MYLIBAPI double add(double a,double b);
MYLIBAPI double mul(double a,double b);
MYLIBAPI char * getString(char* a);

double add(double a,double b){  
 return a + b;
}

double mul(double a,double b){
 return a*b;
}
//定義了一個(gè)返回java String類(lèi)型的參數(shù)
char * getString(char* a){
 char* b ="this is test";
 return strcat(a,b);
}

這里要注意的是:java的String和cpp的String不一樣的,其對(duì)應(yīng)的是char*,如果要用cpp的string不是亂碼就是調(diào)用失敗。

使用VS生成dll

這里變成Release博烂,點(diǎn)擊配置管理器配置x64版本香椎,這樣生成的dll就是x64版本的,這點(diǎn)非常重要禽篱。

配置完成以后右擊項(xiàng)目點(diǎn)擊生成按鈕畜伐。

這一頓操作下來(lái),基本就能夠正確的生成dll了躺率,如果不能生成烤礁,極有可能是你的姿勢(shì)不對(duì),照著文章重新弄一遍肥照,如果還是不行脚仔,你就加我微信問(wèn)我吧。

VS生成的dll文件在哪個(gè)位置呢舆绎?別急鲤脏,我們繼續(xù)。

右擊項(xiàng)目

這里要注意的是在上級(jí)目錄吕朵!不要想當(dāng)然打開(kāi)的項(xiàng)目位置然后直接就去x64去找了猎醇,根本沒(méi)用!里面沒(méi)有dll努溃,是在上級(jí)目錄硫嘶,上級(jí)目錄 的x64位置。

開(kāi)發(fā)Java程序

導(dǎo)入Maven依賴(lài)

新建Maven項(xiàng)目后梧税,在Maven的pom文件中引入如下依賴(lài)沦疾。

 class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="java" cid="n50" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna -->
<dependency>
 <groupId>net.java.dev.jna</groupId>
 <artifactId>jna</artifactId>
 <version>5.3.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna-platform -->
<dependency>
 <groupId>net.java.dev.jna</groupId>
 <artifactId>jna-platform</artifactId>
 <version>5.3.1</version>
</dependency>

指定dll位置

我個(gè)人就放在這個(gè)lib包下面,這樣導(dǎo)入這個(gè)包的時(shí)候可以寫(xiě)絕對(duì)路徑也可以寫(xiě)相對(duì)路徑第队。

編寫(xiě)代碼

注意:這里定義的接口方法名稱(chēng)需要和dll中的方法名稱(chēng)一致哮塞。

 class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="java" cid="n56" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package com.binghe.jni;

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

/**
 * @author binghe
 * @description: 測(cè)試JNI程序
 */
public class JnaTest {
 public interface TestProject extends Library {
 TestProject INSTANCE = (TestProject) Native.load("src/main/lib/testDll.dll",
 JnaTest.TestProject.class);
 public double add(double i, double j);
 public double mul(double i, double j);
 public String getString(String a);

 }

 public static void main(String[] args) {

 System.out.println(TestProject.INSTANCE.add(20.11,20.0));
 System.out.println(TestProject.INSTANCE.mul(16.9,20.89));
 System.out.println(TestProject.INSTANCE.getString("我現(xiàn)在正在測(cè)試dllgihjb"));
 }
}

運(yùn)行Java程序

直接運(yùn)行main方法,得到如下輸出結(jié)果凳谦。

大功告成~~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末忆畅,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子尸执,更是在濱河造成了極大的恐慌家凯,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件如失,死亡現(xiàn)場(chǎng)離奇詭異绊诲,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)岖常,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)驯镊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事板惑¢暇担” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵冯乘,是天一觀的道長(zhǎng)洽胶。 經(jīng)常有香客問(wèn)我,道長(zhǎng)裆馒,這世上最難降的妖魔是什么姊氓? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮喷好,結(jié)果婚禮上翔横,老公的妹妹穿的比我還像新娘。我一直安慰自己梗搅,他們只是感情好禾唁,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著无切,像睡著了一般荡短。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上哆键,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天掘托,我揣著相機(jī)與錄音,去河邊找鬼籍嘹。 笑死闪盔,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的噩峦。 我是一名探鬼主播锭沟,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼抽兆,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼识补!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起辫红,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤凭涂,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后贴妻,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體切油,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年名惩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了澎胡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖攻谁,靈堂內(nèi)的尸體忽然破棺而出稚伍,到底是詐尸還是另有隱情,我是刑警寧澤戚宦,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布个曙,位于F島的核電站,受9級(jí)特大地震影響受楼,放射性物質(zhì)發(fā)生泄漏垦搬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一艳汽、第九天 我趴在偏房一處隱蔽的房頂上張望猴贰。 院中可真熱鬧,春花似錦河狐、人聲如沸糟趾。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)义郑。三九已至,卻和暖如春丈钙,著一層夾襖步出監(jiān)牢的瞬間非驮,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工雏赦, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留劫笙,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓星岗,卻偏偏與公主長(zhǎng)得像填大,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子俏橘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容