linux环境下java调用C/C++动态库(JNI技术:参数为指针与结构体)
一、JNI技术
JNI是Java Native Interface的缩写,通过使用 Java本地接口书写程序,可以确保代码在不同的平台上方便移植.
SUN公司发布的Java 本地接口(JNI)提供了将Java与C/C++、汇编等本地代码集成的方案,该规范使得在 Java 虚拟机内运行的 Java 代码能够与其它编程语言互相操作,包括创建本地方法、更新Java对象、调用Java方法,引用 Java类,捕捉和抛出异常等,也允许Java代码调用 C/C++或汇编语言编写的程序和库。作为一个标准程序接口,它没有对底层 Java虚拟机的实现施加任何限制(特点:二进制兼容、效率高、功能强)
java与JNI数据类型对照表
1、基本数据类型

2、引用数据类型对照表

二、Linux环境的准备(centos7)
1、安装JDK(注意:不能安装openjdk,因为openjdk没有include目录,编译时需要用到include目录的头文件)
2、安装gcc和g++ ( yum install gcc-c++)

3、新建Java工程,在包名为com.ywb.Native下新建"NativeCpp.java"类,方法必须使用native修饰(native即 JNI java native interface)
package com.ywb.Native;
public class NativeCpp {
public native void sayHello();
public native int calculate(int num1, int num2);
public native void output(String url, String newUrl);
}
4、编译生成class文件,进入工程下的target\classes目录下,执行"javah -jni com.ywb.Native.NativeCpp",生成"com_ywb_Native_NativeCpp.h"头文件

4.1:com_ywb_Native_NativeCpp.h文件内容
#include <jni.h>
/* Header for class com_ywb_Native_NativeCpp */ #ifndef _Included_com_ywb_Native_NativeCpp
#define _Included_com_ywb_Native_NativeCpp
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_ywb_Native_NativeCpp
* Method: sayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_ywb_Native_NativeCpp_sayHello
(JNIEnv *, jobject); /*
* Class: com_ywb_Native_NativeCpp
* Method: calculate
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_ywb_Native_NativeCpp_calculate
(JNIEnv *, jobject, jint, jint); /*
* Class: com_ywb_Native_NativeCpp
* Method: output
* Signature: (Ljava/lang/String;Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_ywb_Native_NativeCpp_output
(JNIEnv *, jobject, jstring, jstring); #ifdef __cplusplus
}
#endif
#endif
5、创建c++源码文件( vim jni.cpp),将生成的头文件"com_ywb_Native_NativeCpp.h"拷贝过来,#include "jni.h"改为#include <jni.h>,再加上自己需要实现的c++代码逻辑
#include <jni.h>
/* Header for class com_ywb_Native_NativeCpp */ #ifndef _Included_com_ywb_Native_NativeCpp
#define _Included_com_ywb_Native_NativeCpp
#ifdef __cplusplus
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
extern "C" {
#endif
/*
* * Class: com_ywb_Native_NativeCpp
* * Method: sayHello
* * Signature: ()V
* */
JNIEXPORT void JNICALL Java_com_ywb_Native_NativeCpp_sayHello
(JNIEnv *, jobject){
printf("hello world\n");
} /*
* * Class: com_ywb_Native_NativeCpp
* * Method: calculate
* * Signature: (II)I
* */
JNIEXPORT jint JNICALL Java_com_ywb_Native_NativeCpp_calculate
(JNIEnv *, jobject, jint num, jint newNum){
return num + newNum;
} char* jstringToChar(JNIEnv* env, jstring jstr) {
char* rtn = NULL;
jclass clsstring = env->FindClass("java/lang/String");
jstring strencode = env->NewStringUTF("GB2312");
jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode);
jsize alen = env->GetArrayLength(barr);
jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
if (alen > 0) {
rtn = (char*) malloc(alen + 1);
memcpy(rtn, ba, alen);
rtn[alen] = 0;
}
env->ReleaseByteArrayElements(barr, ba, 0);
return rtn;
}
/*
* * Class: com_ywb_Native_NativeCpp
* * Method: output
* * Signature: (Ljava/lang/String;Ljava/lang/String;)V
* */
JNIEXPORT void JNICALL Java_com_ywb_Native_NativeCpp_output
(JNIEnv *env, jobject, jstring url, jstring newUrl){
char* pUrl1 = jstringToChar(env, url);
char* pUrl2 = jstringToChar(env, newUrl);
printf("url1 = %s\n", pUrl1);
printf("url2 = %s\n", pUrl2); } #ifdef __cplusplus
}
#endif
#endif
6、编译生成动态库
6.1:g++ -fPIC -c jni.cpp -I /home/admin/software/jdk1.8.0_202/include/ -I /home/admin/software/jdk1.8.0_202/include/linux/ 
6.2:g++ -shared jni.o -o jni.so
7、java调用c++动态库
package com.ywb.Native;
public class App {
public static void main( String[] args )
{
//windows环境下加载库
//System.load("D:\\\JniDll.dll");
//linux下加载库
System.load("/root/IdeaProjects/demo/target/classes/jni.so");
NativeCpp nativeCpp = new NativeCpp();
nativeCpp.sayHello();
System.out.println(nativeCpp.calculate(15, 15));
nativeCpp.output("www.baidu.com", "https://www.cnblogs.com/ywbmaster/www.haoservice.cn");
}
}

注:可以将代码封装成jar包,为以后程序方便调用
8、jni方法签名规则

可以进入Java编译后的class文件所在的目录,执行 javap -s 对应Java类的class文件,可以查看当前类下所有方法所对应的签名信息
1、方法例子:
public void example1(int string, float index)
对应签名:
(IF)V
2、方法例子:
public string example2(String string, int index,double d)
对应签名:
(Ljava/util/String;I;D)Ljava/util/String;
3、方法例子:
public int example3(int index, String value,int[] arr)
对应签名:
(ILjava/util/String;[I)I
linux环境下java调用C/C++动态库(JNI技术:参数为指针与结构体)的更多相关文章
- windows和linux环境下java调用C++代码-JNI技术
最近部门做安卓移动开发的需要调C++的代码,困难重重,最后任务交给了我,查找相关资料,没有一个教程能把不同环境(windows,linux)下怎么调用说明白的,自己在实现的过程中踩了几个坑,在这里总结 ...
- Linux环境下如何计算CPU占用率【华为云技术分享】
1.Linux 环境下查看 CPU 信息 1.1.查看 CPU 详细信息 通过 cat /proc/cpuinfo 命令,可以查看 CPU 相关的信息: [root@rh ~]$ cat /proc/ ...
- 解决Linux系统下程序找不到动态库的方法
思路:一般来说,通过make命令已经将程序依赖的动态库编译出来了,通过make install命令已经将动态库安装到系统的某个路径下.找没找到动态库就看这个路径是否包含在系统默认搜索动态库的路径中,如 ...
- Windows 环境下Java调用CRF++详解
1.步骤一览 2.步骤详情 2.1.环境准备 Swig(Simplified Wrapper and Interface Generator)下载,Windows操作系统直接解压即可使用 CRF++( ...
- Linux环境下Java中文乱码解决方案
相信很多朋友遇到过Java的乱码问题,最近我也在解决一个“使用文本生成图片过程中中文以及特殊字符乱码”的问题:花了我大量时间,Debug了sun.font.sun.awt下面的各种源码,终于搞懂了其机 ...
- Linux环境下Java应用性能分析定位-CPU使用篇
1 CPU热点分析定位背景 CPU资源还是很昂贵的,为了深刻感受到这种昂贵,间下图当前CPU的资源售价: 所以对于程序猿们来说,需要让程序合理高效的使用CPU资源.利用有限的CPU资源来解决完 ...
- windows和linux环境下使用google的glog日志库
一.概述 glog是google推出的一款轻量级c++开源日志框架,源码在github上,目前最新release版本是v0.3.5. githut地址:https://github.com/googl ...
- Linux环境下的编译,链接与库的使用
参考博客: http://www.cnblogs.com/qytan36/archive/2010/05/25/1743955.html http://m.blog.csdn.net/article/ ...
- 使用ctypes调用系统C API函数需要注意的问题,函数参数中有指针或结构体的情况下最好不要修改argtypes
有人向我反应,在代码里同时用我的python模块uiautomation和其它另一个模块后,脚本运行时会报错,但单独使用任意一个模块时都是正常的,没有错误.issue链接 我用一个例子来演示下这个问题 ...
- Linux环境下java开发环境搭建二 tomcat搭建
第一步:下载安装包并解压 # tar zxvf 压缩包名 第二步:把解压出的文件移动到/usr/local/tomcat7中 #mv 解压出来的文件夹 /usr/local/tomcat7 第三步: ...
随机推荐
- JS服务端技术—Node.js知识点
[版权声明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) https://www.cnblogs.com/cnb-yuchen/p/18031964 出自[进步*于辰的博客] 目录 1.NP ...
- GIT版本控制学习博客
GIT版本控制学习博客 环境部署 下载git版本控制即可. 用户配置 (1)设置用户及地址 git config --global user.name "Username" git ...
- KingbaseES生成动态SQL
1. 动态SQL 动态SQL在程序启动时会根据输入参数替换相应变量.使用动态SQL可以创建更强大和灵活的应用程序,但在编译时SQL语句的全文不确定,因此运行时编译会牺牲一些性能.动态SQL可以是代码或 ...
- C#/.NET/.NET Core优秀项目和框架2024年3月简报
前言 公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的介绍.功能特点.使用方式以及部分功能截图 ...
- #线段树,离线#CF1000F One Occurrence
题目 给定一个长度为\(n\)序列,\(m\)个询问,每次询问给定一个区间\([l,r]\), 如果这个区间里存在只出现一次的数,输出这个数(如果有多个就输出任意一个),没有就输出0 分析 考虑离线, ...
- #区间dp,离散#D 弱者对决
分析 设\(dp[i][j][x]\)表示当前区间为\([i,j]\),最小值为\(x\)的最大总分, 状态转移方程可以用后缀最大值优化到\(O(n^3m)\),主要难点是输出方案 后缀最大值需要记录 ...
- #子序列自动机,vector#洛谷 3500 [POI2010]TES-Intelligence Test
题目 多组询问查询某个串是否为模式串的子序列 分析 考虑用子序列自动机做,匹配的时候显然选择靠前的,用个vector查询最近的就行了 代码 #include <cstdio> #inclu ...
- 空间音频技术与生态发展高峰论坛成功举办,业界首个Audio Vivid创作工具花瓣三维声亮相
11月26日至27日,UWA世界超高清视频产业联盟(以下简称"UWA联盟").上海交通大学-南加州大学文化创意产业学院.华为联合举办了"互联智慧,共赢未来" 超 ...
- mongodb基础整理篇————索引[四]
前言 简单介绍一些索引. 正文 索引的术语: index 索引 key 键 DataPage 数据页 covered Query: ixscan/collscan: big O Natation: q ...
- redis 简单整理——内存的优化[二十七]
前言 简单介绍一下内存的优化. 正文 Redis所有的数据都在内存中,而内存又是非常宝贵的资源.如何优化内存的使用一直是Redis用户非常关注的问题.本节深入到Redis细节中,探索内存优化的技巧. ...