java jni技术_JNI技术简介

JNI(Java Native Interface)

提供一种Java字节码调用C/C++的解决方案,JNI描述的是一种技术。

fbe3fbdb6230?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

NDK(Native Development Kit)

Android NDK 是一组允许您将 C 或 C++(“原生代码”)嵌入到 Android 应用中的工具,NDK描述的是工具集。 能够在 Android 应用中使用原生代码对于想执行以下一项或多项操作的开发者特别有用:

在平台之间移植其应用。

重复使用现有库,或者提供其自己的库供重复使用。

在某些情况下提高性能,特别是像游戏这种计算密集型应用。

JNI方法注册

静态注册

当Java层调用navtie函数时,会在JNI库中根据函数名查找对应的JNI函数。如果没找到,会报错。如果找到了,则会在native函数与JNI函数之间建立关联关系,其实就是保存JNI函数的函数指针。下次再调用native函数,就可以直接使用这个函数指针。

JNI函数名格式(需将”.”改为”_”):

Java_ + 包名(com.example.auto.jnitest)+ 类名(MainActivity) + 函数名(stringFromJNI)

静态方法的缺点:

要求JNI函数的名字必须遵循JNI规范的命名格式;

名字冗长,容易出错;

初次调用会根据函数名去搜索JNI中对应的函数,会影响执行效率;

需要编译所有声明了native函数的Java类,每个所生成的class文件都要用javah工具生成一个头文件;

动态注册

通过提供一个函数映射表,注册给JVM虚拟机,这样JVM就可以用函数映射表来调用相应的函数,就不必通过函数名来查找需要调用的函数。

Java与JNI通过JNINativeMethod的结构来建立函数映射表,它在jni.h头文件中定义,其结构内容如下:

typedef struct {

const char* name;

const char* signature;

void* fnPtr;

} JNINativeMethod;

创建映射表后,调用RegisterNatives函数将映射表注册给JVM;

当Java层通过System.loadLibrary加载JNI库时,会在库中查JNI_OnLoad函数。可将JNI_OnLoad视为JNI库的入口函数,需要在这里完成所有函数映射和动态注册工作,及其他一些初始化工作。

数据类型转换

基础数据类型转换

fbe3fbdb6230?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

引用数据类型转换

除了Class、String、Throwable和基本数据类型的数组外,其余所有Java对象的数据类型在JNI中都用jobject表示。Java中的String也是引用类型,但是由于使用频率较高,所以在JNI中单独创建了一个jstring类型。

fbe3fbdb6230?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

引用类型不能直接在 Native 层使用,需要根据 JNI 函数进行类型的转化后,才能使用;

多维数组(含二维数组)都是引用类型,需要使用 jobjectArray 类型存取其值;

例如,二维整型数组就是指向一位数组的数组,其声明使用方式如下:

//获得一维数组的类引用,即jintArray类型

jclass intArrayClass = env->FindClass("[I");

//构造一个指向jintArray类一维数组的对象数组,该对象数组初始大小为length,类型为 jsize

jobjectArray obejctIntArray = env->NewObjectArray(length ,intArrayClass , NULL);

JNI函数签名信息

由于Java支持函数重载,因此仅仅根据函数名是没法找到对应的JNI函数。为了解决这个问题,JNI将参数类型和返回值类型作为函数的签名信息。

JNI规范定义的函数签名信息格式:

(参数1类型字符…)返回值类型字符

函数签名例子:

fbe3fbdb6230?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

JNI常用的数据类型及对应字符:

fbe3fbdb6230?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

JNIEnv介绍

JNIEnv概念 :

JNIEnv是一个线程相关的结构体, 该结构体代表了 Java 在本线程的运行环境。通过JNIEnv可以调用到一系列JNI系统函数。

JNIEnv线程相关性:

每个线程中都有一个 JNIEnv 指针。JNIEnv只在其所在线程有效, 它不能在线程之间进行传递。

注意:在C++创建的子线程中获取JNIEnv,要通过调用JavaVM的AttachCurrentThread函数获得。在子线程退出时,要调用JavaVM的DetachCurrentThread函数来释放对应的资源,否则会出错。

JNIEnv 作用:

访问Java成员变量和成员方法;

调用Java构造方法创建Java对象等。

JNI编译

ndkBuild

Cmake编译

CMake 则是一个跨平台的编译工具,它并不会直接编译出对象,而是根据自定义的语言规则(CMakeLists.txt)生成 对应 makefile 或 project 文件,然后再调用底层的编译, 在Android Studio 2.2 之后支持Cmake编译。

add_library 指令

语法:add_library(libname [SHARED | STATIC | MODULE] [EXCLUDE_FROM_ALL] [source])

将一组源文件 source 编译出一个库文件,并保存为 libname.so (lib 前缀是生成文件时 CMake自动添加上去的)。其中有三种库文件类型,不写的话,默认为 STATIC;

SHARED: 表示动态库,可以在(Java)代码中使用 System.loadLibrary(name) 动态调用;

STATIC: 表示静态库,集成到代码中会在编译时调用;

MODULE: 只有在使用 dyId 的系统有效,如果不支持 dyId,则被当作 SHARED 对待;

EXCLUDE_FROM_ALL: 表示这个库不被默认构建,除非其他组件依赖或手工构建;

#将compress.c 编译成 libcompress.so 的共享库

add_library(compress SHARED compress.c)

target_link_libraries 指令

语法:target_link_libraries(target library library2…)

这个指令可以用来为 target 添加需要的链接的共享库,同样也可以用于为自己编写的共享库添加共享库链接。如:

#指定 compress 工程需要用到 libjpeg 库和 log 库

target_link_libraries(compress libjpeg ${log-lib})

find_library 指令

语法:find_library( name1 path1 path2 ...)

VAR 变量表示找到的库全路径,包含库文件名 。例如:

find_library(libX X11 /usr/lib)

find_library(log-lib log) #路径为空,应该是查找系统环境变量路径

Abi架构

ABI(Application binary interface)应用程序二进制接口。不同的CPU 与指令集的每种组合都有定义的 ABI (应用程序二进制接口),一段程序只有遵循这个接口规范才能在该 CPU 上运行,所以同样的程序代码为了兼容多个不同的CPU,需要为不同的 ABI 构建不同的库文件。当然对于CPU来说,不同的架构并不意味着一定互不兼容。

armeabi设备只兼容armeabi;

armeabi-v7a设备兼容armeabi-v7a、armeabi;

arm64-v8a设备兼容arm64-v8a、armeabi-v7a、armeabi;

X86设备兼容X86、armeabi;

X86_64设备兼容X86_64、X86、armeabi;

mips64设备兼容mips64、mips;

mips只兼容mips;

根据以上的兼容总结,我们还可以得到一些规律:

armeabi的SO文件基本上可以说是万金油,它能运行在除了mips和mips64的设备上,但在非armeabi设备上运行性能还是有所损耗;

64位的CPU架构总能向下兼容其对应的32位指令集,如:x86_64兼容X86,arm64-v8a兼容armeabi-v7a,mips64兼容mips;

问题排查 addr2line

03-21 23:59:32.032 6770-6770/? A/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

03-21 23:59:32.032 6770-6770/? A/DEBUG: Build fingerprint: 'google/sdk_gphone_x86/generic_x86:8.1.0/OPM1.171004.001/4376136:user/release-keys'

03-21 23:59:32.032 6770-6770/? A/DEBUG: Revision: '0'

03-21 23:59:32.032 6770-6770/? A/DEBUG: ABI: 'x86'

03-21 23:59:32.032 6770-6770/? A/DEBUG: pid: 6745, tid: 6745, name: ucai.nativedemo >>> com.choufucai.nativedemo <<<

03-21 23:59:32.032 6770-6770/? A/DEBUG: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x70

03-21 23:59:32.032 6770-6770/? A/DEBUG: Cause: null pointer dereference

03-21 23:59:32.032 6770-6770/? A/DEBUG: eax 00000070 ebx a8a6479c ecx 00000035 edx 00000075

03-21 23:59:32.032 6770-6770/? A/DEBUG: esi ffffffff edi ffffffff

03-21 23:59:32.032 6770-6770/? A/DEBUG: xcs 00000073 xds 0000007b xes 0000007b xfs 0000003b xss 0000007b

03-21 23:59:32.032 6770-6770/? A/DEBUG: eip a89a2553 ebp bffa2408 esp bffa1e78 flags 00010202

03-21 23:59:32.228 6770-6770/? A/DEBUG: backtrace:

03-21 23:59:32.228 6770-6770/? A/DEBUG: #00 pc 0001d553 /system/lib/libc.so (strlen+51)

03-21 23:59:32.228 6770-6770/? A/DEBUG: #01 pc 0005fd5d /system/lib/libc.so (__vfprintf+5581)

03-21 23:59:32.228 6770-6770/? A/DEBUG: #02 pc 0008439e /system/lib/libc.so (vsnprintf+222)

03-21 23:59:32.228 6770-6770/? A/DEBUG: #03 pc 00022f30 /system/lib/libc.so (__vsnprintf_chk+48)

03-21 23:59:32.228 6770-6770/? A/DEBUG: #04 pc 000068de /system/lib/liblog.so (__android_log_print+78)

03-21 23:59:32.228 6770-6770/? A/DEBUG: #05 pc 00000ee2 /data/app/com.choufucai.nativedemo-c_F0BwkNYJA0ITdueTXEdg==/lib/x86/libnative-lib.so

03-21 23:59:32.228 6770-6770/? A/DEBUG: #06 pc 00647e67 /system/lib/libart.so (art_quick_generic_jni_trampoline+71)

03-21 23:59:32.228 6770-6770/? A/DEBUG: #07 pc 00641e62 /system/lib/libart.so (art_quick_invoke_stub+338)

03-21 23:59:32.228 6770-6770/? A/DEBUG: #08 pc 00115fdf /system/lib/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+223)

03-21 23:59:32.228 6770-6770/? A/DEBUG: #09 pc 0032143f /system/lib/libart.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+335)

03-21 23:59:32.228 6770-6770/? A/DEBUG: #10 pc 0031a6a4 /system/lib/libart.so

以上错误日志中backtrace就是堆栈信息,#00 #01 就是堆栈列表。 #00 就是堆栈顶层即是错误所在地址,pc后面的就是地址,可以通过以下命令查找出地址可以获得对应的源码文件和行号:

// -f 输出函数名

// -e 输出错误代码行数和文件路径

// xxx.so 对应出错的so文件, 在android工程obj目录下

// addr 是具体的地址

arm-linux-androideabi-addr2line -f -e xxx.so addr

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/573713.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java web redis_java web redis使用(二)

上篇中已经安装好redis&#xff0c;然后下面就说怎么在java web中用客户端来使用regis使用jedis java客户端一&#xff1a;一个简单的示例代码:public static void main(String[] args) {Jedis jedis new Jedis( "147.151.240.234" , 6379 );jedis.set("foo&…

mysql 主从_搭建mysql主从并编写监控主从状态脚本

要求&#xff1a;两台centos7虚拟机分为主和从安装mysqlyum -y install mysql mysql-server关闭防火墙service iptables stopsetenforce 0上面的主从都做。修改主的配置文件vi /etc/my.cnf#添加server-id1log-binmysqlbinrelay-logrelays之后保存退出重启mysql服务service …

Java核心技术点之动态代理

本篇博文会从代理的概念出发&#xff0c;介绍Java中动态代理技术的使用&#xff0c;并进一步探索它的实现原理。由于个人水平有限&#xff0c;叙述中难免出现不清晰或是不准确的地方&#xff0c;希望大家可以指正&#xff0c;谢谢大家&#xff1a;&#xff09; 一、概述 1. 什么…

shell入门之expr的使用

在expr中加减乘除的使用&#xff0c;脚本例如以下&#xff1a; #!/bin/sh #a test about expr v1expr 5 6 echo "$v1" echo expr 3 5 echo expr 6 / 2 echo expr 9 \* 5 echo expr 9 - 6 执行效果 转载于:https://www.cnblogs.com/bhlsheji/p/5401458.html

java中子线程与主线程通信_Android笔记(三十二) Android中线程之间的通信(四)主线程给子线程发送消息...

之前的例子都是我们在子线程(WorkerThread)当中处理并发送消息&#xff0c;然后在主线程(UI线程)中获取消息并修改UI&#xff0c;那么可以不可以在由主线程发送消息&#xff0c;子线程接收呢&#xff1f;我们按照之前的思路写一下代码&#xff1a;packagecn.lixyz.handlertest;…

java开源笔记软件下载_开发常用软件笔记 - ZhaoQian's Blog - OSCHINA - 中文开源技术交流社区...

notepad使用快捷键CtrlH打开“替换对话框”&#xff0c;在每行的开头添加内容。 勾选左下角的“正则表达式”选项 在“查找目标”里输入上尖号“^”&#xff0c;上尖号代表每行的开头 在“替换为”里输入“private String”。然后点"全部替换"按钮&#xff0c;这样每…

极光推送指定用户推送_App用户都睡着了?是时候用推送和活动唤醒一波了!

想要运营好一款App&#xff0c;引流、留存、促活三大环节必不可少。引流解决了用户来的问题&#xff0c;留存解决了用户留下来的问题&#xff0c;而促活解决的是让一部分新注册用户以及许久没有动静的老用户&#xff0c;在平台中再次活跃起来。今天&#xff0c;我们就来聊聊关于…

oracle awr报告生成_分享AWR报告的生成和简单分析方法

生成AWR报告方法&#xff1a;第一步&#xff1a;数据库压力测试卡开始时&#xff1a;生成第一个快照&#xff1a;Sql>exec dbms_workload_repository.create_snapshot();第二步&#xff1a;数据库压力测试结束时&#xff1a;生成第二个快照Sql>exec dbms_workload_reposi…

安卓开发 登录用户信息缓存_在Linux上使用finger命令查询登录用户信息

请关注本头条号&#xff0c;每天坚持更新原创干货技术文章。如需学习视频&#xff0c;请在微信搜索公众号“智传网优”直接开始自助视频学习1. 前言本文主要讲解finger命令的作用和日常使用案例。finger命令是一个用户信息查询命令&#xff0c;它给出了所有登录用户的详细信息。…

POJ 1065 Wooden Sticks

http://blog.csdn.net/acdreamers/article/details/7626671 学习一下Dilworth定理 推荐一篇写得很好博客 要求最少的覆盖&#xff0c;按照Dilworth定理 最少链划分 最长反链长度 所以最少系统 最长导弹高度上升序列长度。 之前写的LIS模板不对。。。。。。 1 #include<cst…

python 对象_Python小课堂面向对象

Python3 面向对象Python从设计之初就已经是一门面向对象的语言&#xff0c;正因为如此&#xff0c;在Python中创建一个类和对象是很容易的。本章节我们将详细介绍Python的面向对象编程。如果你以前没有接触过面向对象的编程语言&#xff0c;那你可能需要先了解一些面向对象语言…

使用jemalloc优化java_Jemalloc优化MySQL和Nginx

Redis 2.4版本之后&#xff0c;默认使用jemalloc来做内存管理&#xff1b;tengine也整合jemalloc。jemalloc从各方评测的结果可见与google tcmalloc都不相伯仲&#xff0c;皆为内存管理器领域最高水平。如下图&#xff1a;最左边的就是glibc的malloc&#xff0c;最右边的就是je…

【代码升级】【iCore3 双核心板】例程二十八:FSMC实验——读写FPGA

实验指导书及代码包下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1i6WL51V 密码&#xff1a;1mk4 iCore3 购买链接&#xff1a; https://item.taobao.com/item.htm?id524229438677 转载于:https://www.cnblogs.com/xiaomagee/p/5409024.html

sqlserver连接字符串_【自学C#】|| 笔记 39 SQL server 连接数据库

一、ADO.NET数据库操作 任何一个应用程序都离不开数据的存储&#xff0c;数据可以在内存中存储&#xff0c;但只能在程序运行时存取&#xff0c;无法持久保存。数据还可以在磁盘中以文件的形式存储&#xff0c;但文件的管理和查找又十分烦琐无法胜任大数量的存储。将数据存储…

Android Studio、 补充知识以及主要组件

转载于:https://www.cnblogs.com/arxk/p/5410597.html

using(){},Close(),Dispose()的区别

//用Close(),Dispose()方式关闭连接 string connString "Data Source(local);Initial CatalogLinq;Integrated SecuritySSPI"; SqlConnection conn new SqlConnection(connString); conn.Open(); conn.Close(); conn.Dispose();//用using方式关闭连接 string connS…

一个域名解析到另一个域名_注册域名公司|教你如何注册一个.net域名

近几年各后缀域名注册量都在增加&#xff0c;很多行业知道线上业务平台搭建的重要性&#xff0c;都优先制作网站布局线上&#xff0c;建站肯定需要域名&#xff0c;所以这也是带动域名注册量上涨原因之一。.COM、.NET域名一直是建站注册域名首选&#xff0c;.COM域名大家可能相…

java jedis connect timed out_Java连接Redis connection timed out 报错的解决方法

Java连接Redis connection timed out 报错的解决方法踩坑场景在使用 RedisTemplate 连接 Redis 进行操作的时候&#xff0c;发生了如下报错&#xff1a;报错信息如下&#xff1a;Caused by: io.netty.channel.ConnectTimeoutException: connection timed out: /192.168.73.10:6…

富文本存储型XSS的模糊测试之道

富文本存储型XSS的模糊测试之道 凭借黑吧安全网漏洞报告平台的公开案例数据&#xff0c;我们足以管中窥豹&#xff0c;跨站脚本漏洞&#xff08;Cross-site Script&#xff09;仍是不少企业在业务安全风险排查和修复过程中需要对抗的“大敌”。 XSS可以粗分为反射型XSS和存储型…

phpstorm xdebug配置

phpstorm 8.0.3版本 1.本身自带xdebug插件 2.在xampp的php.ini中最后中添加&#xff08;如果有[XDebug]配置替换&#xff09; [XDebug]zend_extension "D:\Program Files\xampp\php\ext\php_xdebug.dll";xdebug.profiler_append 0;xdebug.profiler_enable 1;xdebu…