一次JAVA调用C++的.so库的过程
2023-12-29 16:21:43
1、准备好.so文件
2、java代码引入jna jar包
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.9.0</version>
</dependency>
3、代码实现
package com.jimi.tracker.util;
import com.google.common.collect.Lists;
import com.sun.jna.Library;
import com.sun.jna.Native;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* Description:
* <p>
* SO的
* </p>
*
* @Author: leo.xiong
* @CreateDate: 2023/12/27 20:19
* @Email: xionglang@jimilab.com
* @Since:
*/
public class JnaUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(JnaUtil.class);
private static final String OS;
private static final boolean IS_WIN;
private static final String ENCODE = "encode";
private static final String USR_LIB_JIMI_SO = "/usr/lib/jimi";
private static final String SO = ".so";
/**
* 需要使用的so文件
*/
private static final List<String> SO_NAME_LIST = Lists.newArrayList(ENCODE);
static {
OS = System.getProperty("os.name").toUpperCase();
IS_WIN = OS.contains("WIN");
if (!IS_WIN) {
//动态设置JNA参数,如果不动态设置,需要通过-Djna.library.path=/usr/lib/jimi/so 指定JVM参数,so文件名需要lib开头
//System.setProperty("jna.library.path", USR_LIB_JIMI_SO + "/so");
//在当前jar包的resouce/so文件夹,把so文件放入其中
extractSoFromJar(JnaUtil.class.getProtectionDomain().getCodeSource().getLocation().getPath(), USR_LIB_JIMI_SO);
}
}
/**
* 加载Jar包中的so文件
*
* @param jarPath
* @param extractPath
*/
private static void extractSoFromJar(String jarPath, String extractPath) {
File jarFile = new File(jarPath);
try (JarFile jar = new JarFile(jarFile)) {
Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if (!entry.getName().toLowerCase().endsWith(SO)) {
continue;
}
boolean isCopy = false;
for (String soName : SO_NAME_LIST) {
if (entry.getName().contains(soName)) {
isCopy = true;
}
}
if (!isCopy) {
continue;
}
File outputFile = new File(extractPath, entry.getName());
if (outputFile.exists()) {
//文件已存在,先删除旧的so文件
LOGGER.info("文件已存在,先删除旧的so文件:{}", extractPath + "/" + entry.getName());
outputFile.delete();
}
outputFile = new File(extractPath, entry.getName());
if (!outputFile.getParentFile().exists()) {
outputFile.getParentFile().mkdirs();
}
try (InputStream is = jar.getInputStream(entry);
OutputStream os = new FileOutputStream(outputFile)) {
byte[] buffer = new byte[1024];
while (is.read(buffer) > 0) {
os.write(buffer);
}
} catch (IOException ioException) {
LOGGER.warn("读取.so文件失败 fileName: {}", entry.getName(), ioException);
}
}
} catch (IOException ioException) {
LOGGER.warn("获取.so库失败 jarPath: {} extractPath: {}", jarPath, extractPath, ioException);
}
}
/**
* 调用C加密库
*
* @param imei
* @param chipId
* @param type
* @return
*/
public static String encryptValue(String imei, String chipId, Integer type) {
byte[] encryptBytes = new byte[32];
try {
if (IS_WIN) {
return imei;
}
EncodeLibrary.INSTANCE.ImeiChipEncrypt(encryptBytes, imei, chipId, type);
} catch (Exception e) {
LOGGER.warn("加密值获取错误 imei:{} chipId: {} type: {}", imei, chipId, type, e);
return null;
}
return new String(encryptBytes, StandardCharsets.UTF_8);
}
/**
* 调用加密方法
*/
public interface EncodeLibrary extends Library {
/**
* 加密文件名称,指定 JVM参数,文件放在这个路径下面 -Djna.library.path=/usr/lib
* linux 文件名使用lib开头,如文件名【libencode.so】,加载的时候需要去掉lib,使用【encode】
*/
EncodeLibrary INSTANCE = Native.load(ENCODE, EncodeLibrary.class);
/**
* 调用C++加密方法,名称跟.h文件相同
*
* @param output
* @param imei
* @param chip
* @param mode
*/
void ImeiChipEncrypt(byte[] output, String imei, String chip, Integer mode);
}
public static void main(String[] args) {
byte[] encryptBytes = new byte[32];
EncodeLibrary.INSTANCE.ImeiChipEncrypt(encryptBytes, "123456789123123456789", null, 0);
}
}
文章来源:https://blog.csdn.net/xionglangs/article/details/135274761
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!