大家好,我是冰河~~
说起 Java,简略好用,然而 Java 中很多牛逼的技术却逐步被忘记了~~
在 Java 语言呈现之前,很多零碎都是应用 C 和 C ++ 开发的。Java 呈现之后,因为其面向对象的思维更加合乎人们的思维习惯,Java 也不必像 C 和 C ++ 那样须要程序员手动治理内存的调配和回收。说白了,就是简略好用。因为 Java 的诸多长处,使其一跃霸榜编程语言前排很多年。
为了可能和应用 C 和 C ++ 写的程序进行交互,Java 提供了本地办法的个性,也就是咱们常说的 JNI 技术,然而,随着互联网的高速倒退,分布式、微服务、大数据、云计算等技术和框架层出不穷,但大多数框架采纳繁多的语言所开发。JNI 这项 Java 中提供的弱小性能,却逐步的被人忘记了。
为何应用 JNI
最近,冰河在剖析 500 多 TB 的数据,从 500 多 TB 的数据中剖析用户的行为习惯,以便为用户提供更好的产品体验和举荐更加适宜用户的产品。然而,在实现算法的过程中,应用 Java 语言开发的算法从 500 多 TB 的数据中,独自剖析某个用户某段时间的行为时,消耗了极大的工夫开销。无论我如何优化算法,都不能达到预期的成果。很显然,这不合乎性能要求。
一名小伙伴对我说:试试 C 语言嘛。对啊!我为啥不试试用 C 语言写算法啊,于是乎,应用 C 语言写了算法,通过一直的优化和调整,算是初步达到了算法性能要求。然而向数据大屏展现数据的时候,后端还是要以微服务的模式部署,于是我想到了 Java 中的 JNI 技术
注:前面独自写一篇我是如何剖析 500 多 TB 数据的。
如何应用 JNI
先说说应用 JNI 时有哪些坑吧,以防止小伙伴们反复踩坑,这里,大家须要留神的是:在应用 JNI 技术调用 dll 动态链接库时,32 位 dll 只能是 32 位 JDK 去调用,64 位 dll 只能是 64 位 JDK 去调用。这个必须是这样的,如果发现无奈调用或者提醒版本谬误,首先要查看下 JDK 的位数和 dll 的位数是否是对应的。
为了可能让小伙伴们顺利的依照文章开发出本人的 JNI 程序,这里,我就具体的说下如何开发一个 JNI 程序,次要分三个大的方面来阐明如何应用 JNI 技术调用 C 和 C ++ 写的程序。
留神:本文中我应用的是 jna Java 类库实现 JNI 开发。
开发 dll 动态链接库
下载 VS
小伙伴们能够在【冰河技术】公众号回复“vscode”,获取 VS2010 下载链接。
应用 VS 开发 dll
VS 新建我的项目
输出项目名称
抉择空我的项目,点击实现
创立实现后,将上面这段代码复制进去:
#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)
// 这的参数是必须的,也能够定义为.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;}
// 定义了一个返回 java String 类型的参数
char * getString(char* a){
char* b ="this is test";
return strcat(a,b);
}
这里要留神的是:java 的 String 和 cpp 的 String 不一样的,其对应的是 char*, 如果要用 cpp 的 string 不是乱码就是调用失败。
应用 VS 生成 dll
这里变成 Release,点击配置管理器配置 x64 版本,这样生成的 dll 就是 x64 版本的,这点十分重要。
配置实现当前右击我的项目点击生成按钮。
这一顿操作下来,根本就可能正确的生成 dll 了,如果不能生成,极有可能是你的姿态不对,照着文章从新弄一遍,如果还是不行,你就加我微信问我吧。
VS 生成的 dll 文件在哪个地位呢?别急,咱们持续。
右击我的项目
这里要留神的是在下级目录!不要想当然关上的我的项目地位而后间接就去 x64 去找了,基本没用!外面没有 dll,是在下级目录,下级目录 的 x64 地位。
开发 Java 程序
导入 Maven 依赖
新建 Maven 我的项目后,在 Maven 的 pom 文件中引入如下依赖。
<!-- 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 地位
我集体就放在这个 lib 包上面,这样导入这个包的时候能够写绝对路径也能够写相对路径。
编写代码
留神:这里定义的接口办法名称须要和 dll 中的办法名称统一。
package com.binghe.jni;
import com.sun.jna.Library;
import com.sun.jna.Native;
/**
* @author binghe
* @description: 测试 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("我当初正在测试 dllgihjb"));
}
}
运行 Java 程序
间接运行 main 办法,失去如下输入后果。
功败垂成~~
好了,明天就到这儿吧,我是冰河,咱们下期见~~