JavaSE JNI 动态注册本地方法(c语言实现native层)

android stadio jni动态注册函数 JNI静态函数注册,根据Java+packname+method来实现的,名称过长,需要JNI开始时去遍历查找,比较麻烦!这个例子用了动态注册方式。当JAVA层通过System.loadLibrary加载完JNI动态库后,紧接着会查找该库中一个叫JNI_OnLoad 的函数。如果有,就调用它,而动态注册的工作就是在这里完成的。 立即下载

转载请注明出处:http://blog.youkuaiyun.com/geekdonie/article/details/15805573


引言:

最近结合着 Android 源码研究了一下 JNI ,发现 Android 上的 JNI 本地方法绑定使用的不是通过函数名进行绑定的静态绑定,而是使用了不常见的动态绑定。

于是在 JavaSE 中动手实现了一下 JNI 本地方法动态绑定,在实现过程中或多或少的出现了一些问题,而网上搜索到的相关文章大多数只是对 Android 源码的一个摘要,而没有具体在 JavaSE 中的实现,故作此文以补此空白。

本文不涉及 JNI 基础,仅仅是对本地方法动态绑定的一个讲解,不明白 JNI 为何物的小白同学请先 Google 研究一下 JNI 再来~~


动态注册本地方法需要一下几个数据结构与方法(可自行在 jni.h 中查看):

  1. // 该结构表示一个Java本地方法与native层的c方法的映射  
  2. typedef struct {  
  3.     char *name; // Java本地方法名称  
  4.     char *signature; // Java本地方法签名  
  5.     void *fnPtr; // c函数指针  
  6. } JNINativeMethod;  
  7.   
  8. // 该方法在JVM加载完JNI动态库的紧接着被调用,所以可以在这个函数里进行动态注册  
  9. JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved);  
  10.   
  11. // 该方法便是用来进行动态注册的  
  12. // clazz:本地方法所在类  
  13. // methods:表明方法映射关系的结构体数组  
  14. // nMethods:上一个参数的数组大小  
  15. jint (JNICALL *RegisterNatives) (JNIEnv *env, jclass clazz, const JNINativeMethod *methods, jint nMethods);  


首先看一下声明和调用本地方法的 Java 代码:

[java]  view plain copy
  1. public class test {  
  2.   
  3.     static {  
  4.         // 加载JNI动态库  
  5.         System.loadLibrary("test_native");  
  6.     }  
  7.   
  8.     public static native String nativeFunc(String msg);  
  9.   
  10.     public static void main(String[] args) {  
  11.   
  12.         System.out.println(nativeFunc("Hello Native"));  
  13.   
  14.     }  
  15. }  

在这个代码中声明了一个 native 方法 nativeFunc,该方法的作用是将传入的字符串加上"(Sovled)"并然后返回修改后的字符串。


然后看一下 JNI 动态链接库的代码(C语言实现):

  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #include <jni.h>  
  4. #include "test.h"  
  5.   
  6. jstring native_function(JNIEnv *env, jclass cls, jstring msg);  
  7.   
  8. // 定义Java本地方法与JNI动态库中方法的映射关系  
  9. static JNINativeMethod gMethods[] = {  
  10.     {"nativeFunc", "(Ljava/lang/String;)Ljava/lang/String;", (void *)native_function}  
  11. };  
  12.   
  13.   
  14. // 注册本地方法  
  15. static int register_native_methods(JNIEnv *env, const char *clsname, const JNINativeMethod *gMethods, int nums)  
  16. {  
  17.     jclass clazz = (*env)->FindClass(env, clsname);  
  18.     if (clazz == NULL)  
  19.         return JNI_FALSE;  
  20.     if ((*env)->RegisterNatives(env, clazz, gMethods, nums) < 0)  
  21.         return JNI_FALSE;  
  22.     return JNI_TRUE;  
  23. }  
  24.   
  25. JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)  
  26. {  
  27.     JNIEnv *env = NULL;  
  28.     jint result = -1;  
  29.   
  30.     // 获得JNIEnv  
  31.     if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_4) != JNI_OK)  
  32.         return JNI_FALSE;  
  33.   
  34.     // 注册本地方法  
  35.     if (register_native_methods(env, "test", gMethods, sizeof(gMethods) / sizeof(gMethods[0])) != JNI_TRUE)  
  36.         return JNI_FALSE;  
  37.   
  38.     result = JNI_VERSION_1_4;  
  39.     return result;  
  40. }  
  41.   
  42. // 自定义方法,将msg加上"(Solved)"并返回  
  43. jstring native_function(JNIEnv *env, jclass cls, jstring msg)  
  44. {  
  45.     const char *cmsg;  
  46.     char cres[1024];  
  47.     jstring res;  
  48.   
  49.     cmsg = (*env)->GetStringUTFChars(env, msg, JNI_FALSE);  
  50.       
  51.     memset(cres, '\0', 1024);  
  52.     strcat(cres, cmsg);  
  53.     strcat(cres, " (Solved)");  
  54.     res = (*env)->NewStringUTF(env, cres);  
  55.       
  56.     (*env)->ReleaseStringUTFChars(env, msg, cmsg);  
  57.   
  58.     return res;  
  59. }  

这里注意 JNI_OnLoad 方法中的操作,在 Android 源码中,获取 JNIEnv 的代码是 vm->GetEnv((void**) &env, JNI_VERSION_1_4),如果在我们的程序中这样写是错误的,会出现 request for member ‘GetEnv’ in something not a structure or union (或 在非结构或联合中请求成员‘GetEnv’)错误,这是因为 Android 源码中的 native 层的实现使用的是 C++,而我们这里使用的是 C语言,这也是网上搜到的很多文章出现的一个问题


最后便是对代码的编译和运行:

1. 编译生成动态链接库 libtest_native.so:

gcc -fPIC -I $JAVA_HOME/include -I $JAVA_HOME/include/linux -shared -o libtest_native.so test.c

这里的 gcc 选项 -fPIC -shared 是用来生成动态链接库的,PIC选项的作用是生成 Position Independent Code,即生成不依赖与特定地址的机器代码,详细请看:http://stackoverflow.com/questions/5311515/gcc-fpic-option

2. 编译 Java 代码并运行

javac test.java

java -Djava.library.path=. test

注意:这里运行 Java 程序时需要加上 -Djava.library.path=. 来指定库加载位置,否则 Java 程序找不到之前生成的动态链接库。

android jni c 静态注册和动态注册 android jni 静态注册 动态注册 一些基本的操作 静态注册Eclipse 动态注册android studio 立即下载

相关推荐

适合小白的超详细yolov8环境配置+实例运行教程,从零开始教你如何使用yolov8训练自己的数据集(Windows+conda+pycharm)

yolov8源码下载地址:GitHub - ultralytics/ultralytics: NEW - YOLOv8 🚀 in PyTorch > ONNX > OpenVINO > CoreML > TFLiteyolov8使用文档: Home - Ultralytics YOLOv8 Docs教学视频参考: 包会!YOLOv8训练自己的数据集_哔哩哔哩_bilibili先用conda prompt创建一个虚拟环境,我的叫yolov8, python版本用3.10 源码地址:GitHub - ul

CV在读 25万+

JNI系列入门之C语言与Java的双向通信(一)

JNI系列文章: JNI系列之入门Hello JNI C(一) JNI系列之入门Hello JNI C(二) JNI系列入门之C语言与Java的双向通信(一) JNI系列入门之C语言与Java的双向通信(二) JNI系列入门之C语言中文字符串乱码问题 一、概述 Java层向C层通信 通过调用静态无参数、有参数的native方法 通过调用非静态无参数、有参数的native方法 C...

weixin_33985507的博客 368

使用单调栈求解最大矩形面积问题的C++实现

通过本文的介绍,我们详细讲解了如何使用单调栈求解砖墙中最大矩形面积的问题,并提供了完整的C++代码实现。希望通过本文的学习,你能掌握单调栈的基本概念及其在实际问题中的应用。如果你有任何疑问或建议,欢迎在评论区留言交流。

m0_57781768的博客 814

registerNativeMethods

Android JNI和NDK关系  1、什么JNI Java Native Interface (JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI 是本地编程接口,它使得在 Java 虚拟机 (VM) 内部运行的 Java 代码能够与用其它编程语言(如 C、C++ 和汇编语言)编写的应用程序和库进行交互操作。 上面过程分为2个部分: 第一、用C语言

xak的专栏 2025

西门子S7-1200/1500 PLC编程与应用技巧

西门子S7-1200 PLC是一款紧凑型的控制器,适用于小型到中型的自动化控制任务。紧凑设计:集成了I/O模块,减少了控制柜的空间需求。高性能:高达25µs的扫描时间,能够快速响应。模块化扩展:支持扩展输入输出模块、通信模块和智能模块,满足不同的应用需求。多种编程语言:支持Ladder图(梯形图)、功能块图(FBD)、结构化文本(ST)等多种编程语言。西门子S7-1200与S7-1500 PLC是强大且灵活的工业控制系统,适用于各种自动化应用。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 2674

避坑指南:ZYNQ MPSOC QSPI固化时MT25QU256闪存的特殊配置

本文针对Xilinx ZYNQ UltraScale+ MPSoC平台,详细解析了使用Vitis工具将BOOT.bin固化至Micron MT25QU256ABA QSPI NOR Flash时的特殊配置与避坑指南。重点阐述了Init文件的真实作用、电压与频率的精确匹配策略,以及针对该闪存型号的初始化序列,帮助工程师解决烧录失败、启动异常等常见问题,确保系统可靠启动。

weixin_29175469的博客 271

JNI通过动态注册实现native函数

一、概述 上一篇写的是通过javah工具将java代码中的native声明的函数生成标准的C/C++函数头,每个函数的名字都很长(Java_包名_类名_函数名),这样C/C++函数的函数名就是定死的,不能修改,否则java找不到函数。这里还有种方式,通过注册的方式将C/C++的函数与java中的native函数进行一一对应的,函数名可以任意书写。二、代码实现 Si...

weixin_33772645的博客 299

433M无线遥控器EV1527协议解码实战:从逻辑分析到代码优化

本文详细解析了433M无线遥控器EV1527协议的实战解码过程。从使用逻辑分析仪抓取波形、理解同步头与数据位编码原理开始,逐步深入代码实现。文章重点对比了原始定时器轮询法的痛点,并提出了基于“边沿捕获+时间戳”的优化方案,构建了高效、可移植且具备抗干扰能力的解码引擎,最后分享了跨平台移植的核心技巧。

weixin_29168813的博客 927

JNI动态注册、静态注册实例及其实现原理分析

想要彻底学好JVM需要一定C语言基础,要理解头文件、指针、结构体、结构体指针、函数指针、类型别名等概念,本文尽量通俗易懂的介绍JNI 一、什么是JNI JNI全名Java Native Interface中文名java本地开发接口。通过JNI可以让java代码调用C或C++等底层语言,也可以用C或C++调用java语言,是java与其他语言交互的协议和桥梁,可以保证java代码的可移植性。 二、为什么要用JNI 当你无法用纯Java来实现需求的时候,就需要使用JNI来用底层语言编写的本地方法来满足这些该需求

yangxiaofei_java的博客 2041

模型预测控制(MPC)算法介绍

模型预测控制(Model Predictive Control,MPC)是一种先进的控制策略,广泛应用于工业过程控制、机器人控制、电力系统等领域。它基于系统的模型,通过滚动优化来预测系统未来的行为,并据此确定当前的最优控制输入。

AI的内部世界的博客 7175

如何在非序列模式下使用类似图像模功能

如何在非序列模式下使用类似图像模功能

weixin_72050316的博客 552

JNI学习

JNI是在学习Android HAL时必须要面临一个知识点,如果你不了解它的机制,不了解它的使用方式,你会被本地代码绕的晕头转向,JNI作为一个中间语言的翻译官在运行Java 代码的Android中有着重要的意义,这儿的内容比较多,也是最基本的,如果想彻底了解JNI的机制,请查看: ? http://docs.oracle.com/javase/1.5.0/docs/guide/jni

u013790419的专栏 862

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

JavaSE(十三)跨语言调用

Java的平台无关性   Java是一种与软硬件平台无关的语言,之所以能实现这一点,是因为与平台相关的操作都由JRE屏蔽了,为了屏蔽平台相关的操作,JRE本身是平台相关的,所以不同的平台需要安装相应运行平台的JRE(JRE包含JVM与Java自带的标准包)。 JNI简介   通过程序对操作系统进行操作,须要通过操作系统提供的系统调用,而操作系统提供的系统调用几乎都不是Java所写,所以Java自带...

墨香院 478

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

深入浅出 - Android系统移植与平台开发(九)- JNI介绍

JNI是在学习Android HAL时必须要面临一个知识点,如果你不了解它的机制,不了解它的使用方式,你会被本地代码绕的晕头转向,JNI作为一个中间语言的翻译官在运行Java代码的Android中有着重要的意义,这儿的内容比较多,也是最基本的,如果想彻底了解JNI的机制,请查看:http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/desi

mr_raptor的专栏 1万+

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

JNI学习(转)

博客分类: AndroidJava、 javaandroid  JNI是在学习Android HAL时必须要面临一个知识点,如果你不了解它的机制,不了解它的使用方式,你会被本地代码绕的晕头转向,JNI作为一个中间语言的翻译官在运行Java 代码的Android中有着重要的意义,这儿的内容比较多,也是最基本的,如果想彻底了解JNI的机制,请查看:   http://do

zs10hz的专栏 536

JNI Design Overview

翻译自 https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/design.html Chapter 2 本章重点介绍JNI中的主要设计问题。 本节中的大多数设计问题都与本地方法有关。 第5章将介绍调用API的相关设计。 JNI Interface Functions and Pointers 本地代码通...

milanac007的专栏 215

JNI 概述

JNI全称 Java Native Interface,Java本地化接口。主要的作用是为Java层和C/C++ Native层的接口调用提供桥梁。在Android系统中,NDK将JNI进行了封装,用于在Java层调用native层复杂的算法以及音视频解码等。

weixin_34764432的博客 231

JNI基础知识

JNI是在学习Android HAL时必须要面临一个知识点,如果你不了解它的机制,不了解它的使用方式,你会被本地代码绕的晕头转向,JNI作为一个中间语言的翻译官在运行Java代码的Android中有着重要的意义,这儿的内容比较多,也是最基本的,如果想彻底了解JNI的机制,请查看: http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/de

u013378580的博客 2944

JNI介绍

JNI是在学习Android HAL时必须要面临一个知识点,如果你不了解它的机制,不了解它的使用方式,你会被本地代码绕的晕头转向,JNI作为一个中间语言的翻译官在运行Java 代码的Android中有着重要的意义,这儿的内容比较多,也是最基本的,如果想彻底了解JNI的机制,请查看: http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec

weakstar的专栏 1006

jni小结

Jni(java native interface)是一种技术,它让java调用其他语言的代码,比如C/C++的代码.在SUN的官方网站上可以下载到相关的文档,看文档总是比较好的,给出链接先: JVM TOOL DOC: http://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html JNI DOC: http:

奋斗 1469
上一篇: JNI 返回结构体参数
下一篇: Java 泛型小结
lcathm
博客等级 码龄18年 37粉丝 44原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值