JNI调用dll库或so库
一、应用场景
如果想用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库相关推荐
- java jni dll路径_Java中Jni调用DLL文件试验
Java中Jni调用DLL文件试验 下面是小编整理的Java中Jni调用DLL文件试验内容,希望可以为您带来帮助!更多内容请关注应届毕业生考试网! 所有文件均在E:\路径下. 安装jdk1.6.0_0 ...
- JNI调用两层C++动态库
最近的Spark项目需要访问TSSD存储,由后台同学提供一个C++动态库,包含读写接口,然后我通过JNI包装so库,调用C++方法. 在Spark中如何使用JNI调用C++动态库,这篇文章讲的很清楚了 ...
- Windows系统下通过JNI调用dll动态库的实现
目的:java代码使用jni获取数据 工具: eclipse + Microsoft visual studio (c++) 业务代码: Java代码业务实现: package com.weip.jn ...
- windows7下,Java中利用JNI调用c++生成的动态库的使用步骤
1.从http://www.oracle.com/technetwork/java/javase/downloads/jdk-7u2-download-1377129.html下载jdk-7u2-wi ...
- jar包调用dll lib等外部库文件失败解决办法
失败问题分析: 路径错误,相对路径和绝对路径的区别(dll等文件无法打入jar包,dll文件位置是相对路径) 打包项目之后就调用不到dll文件 Java运行JDK32位还是64位 代码更改 使用Sys ...
- java jni调用dll文件_Java通过jni调用动态链接库
(1)JNI简介 JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信(主要是C&C++).从Java1.1开始,JNI标准成为java ...
- JNI的方式调用DLL(SO)(上)
最近有个项目要调用原有的DLL文件,本来准备使用JNA,可是客户不同意,非要使用JNI的方式.万般无奈之下,只能重新使用JNI,现将JAVA调用动态链接库的一般方法总结如下. JNI是Java Nat ...
- android调用 qt so文件路径,Android Java调用Qt写的so库
有时候,我们反编译apk得到一个so库,如果直接使用这个so库的话,必须使用原来so库同样的package名字,才能用.这样人家反编译你的apk,就知道你侵犯了人家的版权.为了达到混淆的目的,我们可以 ...
- java中通过JNA调用dll
---恢复内容开始--- 1. JNA简单介绍 先说JNI(Java Native Interface)吧,有过不同语言间通信经历的一般都知道,它允许Java代码和其他语言(尤其C/C++)写的代码进 ...
- Android Jni 调用
Chap1:JNI完全手册... 3 Chap2:JNI-百度百科... 11 Chap 3:javah命令帮助信息... 16 Chap 4:用javah产生一个.h文件... 17 Chap5:j ...
最新文章
- 运维企业专题(11)RHCS高可用集群下MySql数据库与共享磁盘(单点写入、多点写入)的设置
- 数据结构 -- 队列
- linux 上配置swoole
- Windows CE授权费用
- 大促密集,CDN如何保障电商体验如丝般顺滑?
- Java 7:WatchService
- 主干开发前要知道的,4错误认识+3优势
- 弹簧触摸开关原理图_电梯弹簧抱闸调整
- jQuery.extend函数
- sql azure 语法_如何将内部SQL Server数据库迁移到Azure
- 腾讯网易已称王,今日头条有什么勇气来做游戏?
- 【Xamarin 开发 IOS --IOS 页面导航概念Segue】
- LC60 Permutation Sequence
- UDK开发环境搭建完全流程
- JAVA 类与对象 1.Tank(用于刻画坦克)和Fight(主类)2.计算机中放入CD即计算机将CD类型的对象作一个成员变量。3.编写程序模拟一个家族成员的姓名,姓名由两部分构成:姓氏和名字。
- Ps快捷切图psd文件及将psd内容转化为CSS样式工具(PxCook)
- 成为研究生后你都明白了什么?
- Vanishing Point Detection 消影点/消失点/灭点检测代码学习整理笔记
- 深度学习环境配置:ubuntu 16.04 安装2080ti驱动 cuda9.0和cudnn7.3 anaconda3.7 tensorflow12.0
- 经常看直播,你知道如何用jmeter对直播间进行压力测试吗?
热门文章
- Android 仿美团GridView分页滑动(类似直播礼物列表效果)
- 虚拟内存与物理内存与内存碎片-杂谈
- 单片机c语言1ms程序,51单片机c语言延时函数 Void delay 1ms(unsigned int ms){un
- Google浏览器Chrome,永久开启flash支持的办法
- MAC表、ARP表、IP路由表区别比较
- 计算机网络技术超星尔雅章节检测,超星尔雅计算机网络技术第二章节测验答案...
- 斐波那契堆 - 解析与实现
- 华为rh5885服务器oid_高性能全冗余 华为RH5885 V3服务器解析
- 收获与期待——2016第四届中国计算机行业发展成就奖揭晓
- Latex同时添加中英文摘要