一、应用场景

如果想用Java调用C或C++程序,前提是给定了C或C++的动态库dll(Windows)或so(Linux)文件和函数头文件说明,根据头文件编写JNI文件,最后根据JNI文件编写Java程序。

二、应用过程

1、Windows环境

1.1、首先得到dll库文件和头文件说明

​​

1.2、根据头文件编写JNI文件

1.2.1、编写JNI头文件cn.bk.test.Native.h

//引入jni头
#include <jni.h>//此处声明具体的函数
extern "C" {/** Class:     cn_bk_test_Native* Method:    comEncryptionProcEX* Signature: (I[BI[B[I)I*/JNIEXPORT jint JNICALL Java_cn_bk_test_Native_comEncryptionProcEX(JNIEnv*, jclass, jint, jint, jint, jbyteArray, jint, jbyteArray, jintArray);}

1.2.2、编写JNI类文件cn.bk.test.Native.c

//引入头
#include "cn_bk_test_Native.h"//----------------------------------------------------------------------------
// 功能   调用密码机上的对称密钥索引号,进行加解密
// 输入   comID       输入      输入:算法标识                      输出:无
//      keyIndex    输入      输入:指定对称密钥索引号             输出:无
//      openSeal    输入      输入:加/解密标志                    输出:无
//      inData      输入      输入:明文/密文                     输出:无
//      inLen       输入      输入:明文/密文长度               输出:无
//      outData     输入/输出   输入:密文/明文存储空间                 输出:密文/明文
//      outLen      输入/输出   输入:密文/明文存储空间长度           输出:密文/明文长度
// 返回   0:  0
//      错误,返回错误代码
//----------------------------------------------------------------------------
JNIEXPORT jint JNICALL Java_cn_bk_test_Native_comEncryptionProcEX
(JNIEnv* env, jclass jobj, jint comID, jint keyIndex, jint openSeal, jbyteArray inData, jint inLen, jbyteArray outData, jintArray outLen) {unsigned char* c_inData = (*env)->GetByteArrayElements(env, inData, NULL);unsigned char* c_outData = (*env)->GetByteArrayElements(env, outData, NULL);int* c_outLen = (*env)->GetIntArrayElements(env, outLen, NULL);int ret = comSymmetryCryptionProc_EX(comID, keyIndex, openSeal, c_inData, inLen, c_outData, c_outLen);(*env)->ReleaseByteArrayElements(env, inData, c_inData, 0);(*env)->ReleaseByteArrayElements(env, outData, c_outData, 0);(*env)->ReleaseIntArrayElements(env, outLen, c_outLen, 0);return ret;
}

注意:

  • JNI中的函数的命名规则:Java_(Java中的包名)cn_bk_test_(Java中的类名)Native_(Java中的方法名)comEncryptionProcEX
  • JNI函数中不存在方法重构,即方法名不能重复

1.3、根据编写的JNI文件生成Java直接调用的dll文件

1.3.1、下载安装mingw_64位, 并将其安装目录配置到系统环境变量

mingw_64位最新下载地址:https://sourceforge.net/projects/mingw-w64/files/


        该软件的作用是在windows系统使用gcc和g++命令,对c文件和c++文件进行编译,生成.o文件, 进而生成.dll文件。64位的只能生成64位的dll文件。若要生成32位的dll文件,请下载32位的mingw.
        mingw_32最新版下载地址:https://sourceforge.net/projects/mingw/files/Installer/
        安装完后将{minw安装目录}\mingw64\bin放到path即可。

1.3.2、生成 .o文件

执行命令: gcc -c -I"%JAVA_HOME%\include" - I"%JAVA_HOME%\include\win32" cn_bk_test_Native.c

1.3.2、生成 .dll文件

执行命令: gcc -Wl,--add-stdcall-alias -shared -o [要生成的dll文件]cn_bk_test_Native.dll [上一步生成的.o文件]cn_bk_test_Native.o [依赖的C程序dll文件]test64.dll

注:如果报系统位数错误则检查C程序性的dll文件编译环境与你此刻编译的系统环境是否相同。

1.4、编写最终调用的Java程序

1.4.1、创建Java工程

1.4.2、创建类:cn.bk.test.Native

public class Native {/*** 调用密码机上的对称密钥索引号,进行加解密.** @param comID    输入   算法标识 0x00200000(sm1) 0x00400000(sm4)* @param keyIndex 输入   指定对称密钥索引号(需要使用密码机管理工具,在索引号的位置生成128bit对称密钥)* @param openSeal 输入   加/解密标志:0 加密 1 解密* @param inData   输入   明文/密文* @param inLen    输入   明文/密文长度* @param outData  输出   密文/明文存储空间* @param outLen   输出   密文/明文存储空间长度* @return 返回错误代码*/public static native int comEncryptionProcEX(int comID,int keyIndex,int openSeal,byte[] inData,int inLen,byte[] outData,int[] outLen);}

1.4.3、直接调用

    /*** SM1对称加解密.** @param keyIndex 容器号* @param openSeal 0 加密 1 解密* @param srcData  Base64编码待加密/解密数据* @return Base64编码加密/解密数据*/public static void sm1CryptionProc(int keyIndex, int openSeal, String srcData) {byte[] inData = Base64Decoder.decode(srcData);//给足够大的空间byte[] outData = new byte[20000];int[] outDataLen = {20000};int n = Native.comEncryptionProcEX(0x00200000, keyIndex, openSeal, inData, inData.length, outData, outDataLen);if (n != 0) {System.out.println("失败");} else {System.out.println("成功,结果:" + Base64Encoder.encode(makeByteArray(outData, outDataLen[0])));}}/*** 拷贝有效数据.** @param src    原数据* @param srcLen 原数据长度* @return 有效数据*/public static byte[] makeByteArray(byte[] src, int srcLen) {byte[] finalData = new byte[srcLen];System.arraycopy(src, 0, finalData, 0, srcLen);return finalData;}

2、Linux环境

2.1、首先得到so库文件和头文件说明

2.2、根据头文件编写JNI文件(同上)

2.3、根据编写的JNI文件生成Java直接调用的so文件

2.3.1、生成 .o文件

执行命令: cc -fPIC -c -I . -I "%JAVA_HOME%/include" -I "%JAVA_HOME%/include/linux" cn_bk_test_Native.c -pthread

2.3.2、生成 .so文件

执行命令: gcc -fPIC -shared -o [要生成的so文件]libcn_bk_test_Native.so [上一步生成的.o文件]cn_bk_test_Native.o [依赖的C程序so文件]test64.so -lpthread

2.4、编写最终调用的Java程序(同上)

三、C-JNI-JAVA类型对照表

C类型  JNI类型 Java类型
unsigned char jboolean Boolean
unsigned char* jbyteArray byte[]
char jbyte Byte
char* jstring String
unsigend short jchar Char
short jshort Short
int jint Integer
unsigned int jint int
unsigned int* jintArray int[]
long long jlong Long
float jfloat Float
double jdouble Double
void** &jintArray int[]
SGD_UINT8* jbyteArray byte[]
SGD_UINT32 jint int
SGD_UINT32* jintArray int[]
DWORD jint int

四、解决返回字符串乱码问题

详见:https://www.jianshu.com/p/4f38bd3bccc0

JNI调用dll库或so库相关推荐

  1. java jni dll路径_Java中Jni调用DLL文件试验

    Java中Jni调用DLL文件试验 下面是小编整理的Java中Jni调用DLL文件试验内容,希望可以为您带来帮助!更多内容请关注应届毕业生考试网! 所有文件均在E:\路径下. 安装jdk1.6.0_0 ...

  2. JNI调用两层C++动态库

    最近的Spark项目需要访问TSSD存储,由后台同学提供一个C++动态库,包含读写接口,然后我通过JNI包装so库,调用C++方法. 在Spark中如何使用JNI调用C++动态库,这篇文章讲的很清楚了 ...

  3. Windows系统下通过JNI调用dll动态库的实现

    目的:java代码使用jni获取数据 工具: eclipse + Microsoft visual studio (c++) 业务代码: Java代码业务实现: package com.weip.jn ...

  4. windows7下,Java中利用JNI调用c++生成的动态库的使用步骤

    1.从http://www.oracle.com/technetwork/java/javase/downloads/jdk-7u2-download-1377129.html下载jdk-7u2-wi ...

  5. jar包调用dll lib等外部库文件失败解决办法

    失败问题分析: 路径错误,相对路径和绝对路径的区别(dll等文件无法打入jar包,dll文件位置是相对路径) 打包项目之后就调用不到dll文件 Java运行JDK32位还是64位 代码更改 使用Sys ...

  6. java jni调用dll文件_Java通过jni调用动态链接库

    (1)JNI简介 JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信(主要是C&C++).从Java1.1开始,JNI标准成为java ...

  7. JNI的方式调用DLL(SO)(上)

    最近有个项目要调用原有的DLL文件,本来准备使用JNA,可是客户不同意,非要使用JNI的方式.万般无奈之下,只能重新使用JNI,现将JAVA调用动态链接库的一般方法总结如下. JNI是Java Nat ...

  8. android调用 qt so文件路径,Android Java调用Qt写的so库

    有时候,我们反编译apk得到一个so库,如果直接使用这个so库的话,必须使用原来so库同样的package名字,才能用.这样人家反编译你的apk,就知道你侵犯了人家的版权.为了达到混淆的目的,我们可以 ...

  9. java中通过JNA调用dll

    ---恢复内容开始--- 1. JNA简单介绍 先说JNI(Java Native Interface)吧,有过不同语言间通信经历的一般都知道,它允许Java代码和其他语言(尤其C/C++)写的代码进 ...

  10. Android Jni 调用

    Chap1:JNI完全手册... 3 Chap2:JNI-百度百科... 11 Chap 3:javah命令帮助信息... 16 Chap 4:用javah产生一个.h文件... 17 Chap5:j ...

最新文章

  1. 运维企业专题(11)RHCS高可用集群下MySql数据库与共享磁盘(单点写入、多点写入)的设置
  2. 数据结构 -- 队列
  3. linux 上配置swoole
  4. Windows CE授权费用
  5. 大促密集,CDN如何保障电商体验如丝般顺滑?
  6. Java 7:WatchService
  7. 主干开发前要知道的,4错误认识+3优势
  8. 弹簧触摸开关原理图_电梯弹簧抱闸调整
  9. jQuery.extend函数
  10. sql azure 语法_如何将内部SQL Server数据库迁移到Azure
  11. 腾讯网易已称王,今日头条有什么勇气来做游戏?
  12. 【Xamarin 开发 IOS --IOS 页面导航概念Segue】
  13. LC60 Permutation Sequence
  14. UDK开发环境搭建完全流程
  15. JAVA 类与对象 1.Tank(用于刻画坦克)和Fight(主类)2.计算机中放入CD即计算机将CD类型的对象作一个成员变量。3.编写程序模拟一个家族成员的姓名,姓名由两部分构成:姓氏和名字。
  16. Ps快捷切图psd文件及将psd内容转化为CSS样式工具(PxCook)
  17. 成为研究生后你都明白了什么?
  18. Vanishing Point Detection 消影点/消失点/灭点检测代码学习整理笔记
  19. 深度学习环境配置:ubuntu 16.04 安装2080ti驱动 cuda9.0和cudnn7.3 anaconda3.7 tensorflow12.0
  20. 经常看直播,你知道如何用jmeter对直播间进行压力测试吗?

热门文章

  1. Android 仿美团GridView分页滑动(类似直播礼物列表效果)
  2. 虚拟内存与物理内存与内存碎片-杂谈
  3. 单片机c语言1ms程序,51单片机c语言延时函数 Void delay 1ms(unsigned int ms){un
  4. Google浏览器Chrome,永久开启flash支持的办法
  5. MAC表、ARP表、IP路由表区别比较
  6. 计算机网络技术超星尔雅章节检测,超星尔雅计算机网络技术第二章节测验答案...
  7. 斐波那契堆 - 解析与实现
  8. 华为rh5885服务器oid_高性能全冗余 华为RH5885 V3服务器解析
  9. 收获与期待——2016第四届中国计算机行业发展成就奖揭晓
  10. Latex同时添加中英文摘要