Loading...
墨滴

冰河

2021/03/27  阅读:45  主题:嫩青

Java中一个逐渐被遗忘的强大功能,强到你难以置信!!

大家好,我是冰河~~

说起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动态链接库

下载VSCode

小伙伴们可以在【冰河技术】公众号回复“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方法,得到如下输出结果。

大功告成~~

好了,今天就到这儿吧,我是冰河,大家有啥问题可以在下方留言,也可以加我微信:sun_shine_lyz,我拉你进群,一起交流技术,一起进阶,一起牛逼~~

冰河原创PDF

关注 冰河技术 微信公众号:

回复 “并发编程” 领取《深入理解高并发编程(第1版)》PDF文档。

回复 “并发源码” 领取《并发编程核心知识(源码分析篇 第1版)》PDF文档。

回复 “我要进大厂” 领取《我要进大厂系列之面试圣经(第1版)》PDF文档。

回复 ”限流“ 领取《亿级流量下的分布式解决方案》PDF文档。

回复 “设计模式” 领取《深入浅出Java23种设计模式》PDF文档。

回复 “Java8新特性” 领取 《Java8新特性教程》PDF文档。

回复 “分布式存储” 领取《跟冰河学习分布式存储技术》 PDF文档。

回复 “Nginx” 领取《跟冰河学习Nginx技术》PDF文档。

回复 “互联网工程” 领取《跟冰河学习互联网工程技术》PDF文档。

写在最后

如果你觉得冰河写的还不错,请微信搜索并关注「 冰河技术 」微信公众号,跟冰河学习高并发、分布式、微服务、大数据、互联网和云原生技术,「 冰河技术 」微信公众号更新了大量技术专题,每一篇技术文章干货满满!不少读者已经通过阅读「 冰河技术 」微信公众号文章,成功跳槽到大厂;也有不少读者实现了技术上的飞跃,成为公司的技术骨干!如果你也想像他们一样提升自己的能力,实现技术能力的飞跃,进大厂,升职加薪,那就关注「 冰河技术 」微信公众号吧,每天更新超硬核技术干货,让你对如何提升技术能力不再迷茫!

冰河

2021/03/27  阅读:45  主题:嫩青

作者介绍

冰河