Android JNI对象与Java对象的绑定

android framework层怎么调用jni层接口 在Android Framework层调用JNI层接口的流程如下:在Java类中声明Native方法。生成JNI头文件。在C/C++中实现Native方法。编译Native代码为共享库。在Java代码中加载Native库。调用Native方法。通过JNI,Android Framework层可以与底层系统(如Linux内核)进行交互,实现高性能的功能开发。 阅读详情

在Android 开发过程中,经常会用到JNI,要么就是Java调用JNI,要么就是JNI回调Java。一种习惯的做法是把在Java和JNI 都生成相同名字的Class,并将它们互相绑定,这样双方互相调用也非常方便。

例如定义Java class:

public final class NativeTest {
    private static final String TAG = NativeFfmpeg.class.getSimpleName();

    static {
        System.loadLibrary("test");
        NativeTest.nativeClassInit();
    }
    
    public static native void nativeClassInit();
    private native void native_setup();
    private native void native_release();
    private native void native_test(int value);

    // bind to Jni class
    private long mNativeHandle = 0;

    private void onResult(int result) {
        Log.e(TAG, "result = " + result);
    }
}
JNI 文件如下:
#define SAFE_FREE(p)  if(p){free(p);p=NULL;}
#define DELETE_LOCAL_REF(env, obj)  if(obj!=NULL){env->DeleteLocalRef(obj);obj=NULL;}
#define DELETE_GLOBAL_REF(env, obj) if(obj!=NULL){env->DeleteGlobalRef(obj);obj=NULL;}
#define DELETE_WEAK_GLOBAL_REF(env, obj) if(obj!=NULL){env->DeleteWeakGlobalRef(obj);obj=NULL;}

#define JNI_FIELDID(name, field) fieldID_##name_##field
#define JNI_METHODID(name, method) methodID_##name_##method
#define JNI_DEFINE_FIELDID(name, field) static jfieldID JNI_FIELDID(name, field) = NULL;
#define JNI_DEFINE_METHODID(name, method) static jmethodID JNI_METHODID(name, method) = NULL;
#define JNI_LOAD_FIELDID(env, clazz, name, field, sig) {JNI_FIELDID(name, field) = (env)->GetFieldID(clazz, #field, sig);__android_log_print(ANDROID_LOG_DEBUG, SV_LOGTAG, "fieldID_"#name"_"#field" = %p", JNI_FIELDID(name, field));}
#define JNI_LOAD_METHODID(env, clazz, name, method, sig) {JNI_METHODID(name, method) = (env)->GetMethodID(clazz, #method, sig);__android_log_print(ANDROID_LOG_DEBUG, SV_LOGTAG, "methodID_"#name"_"#method" = %p", JNI_METHODID(name, method));}

JNI_DEFINE_FIELDID(NativeTest, mNativeHandle);
JNI_DEFINE_METHODID(NativeTest, onResult);

class NativeTest
{
private:
    jweak mObject;

public:
    NativeTest():mObject(NULL){};
    ~NativeTest(){unbind(NULL)};
public:
    void bind(JNIEnv* env, jobject obj)
    {
        jclass clazz = env->GetObjectClass(obj);
        // refer to Java object
        mObject = env->NewWeakGlobalRef(obj);
        DELETE_LOCAL_REF(env, clazz);
        // bind this Jni object to its Java object(reference)
        env->SetLongField(mObject, JNI_FIELDID(NativeTest, mNativeHandle), (jlong)this);
    }
    void unbind(JNIEnv* env)
    {
        if(env == NULL)
        {
            jvm->AttachCurrentThread(&env, NULL);
        }
        env->SetLongField(mObject, JNI_FIELDID(NativeTest, mNativeHandle), (jlong)0);
        DELETE_WEAK_GLOBAL_REF(env, mObject);
    }
    void test(JNIEnv* env, int value)
    {
        if(env == NULL)
        {
            jvm->AttachCurrentThread(&env, NULL);
        }    
        if(mObject != NULL && JNI_METHODID(NativeTest, onResult) != NULL)
        {
            env->CallVoidMethod(mObject, JNI_METHODID(NativeTest, onResult), ++value);
        }
    }
}

static void nativeClassInit(JNIEnv* env, jclass clazz)
{
    jclass clazz = env->FindClass(kNativeTestPath);
    
    JNI_LOAD_FIELDID(env, clazz, NativeTest, mNativeHandle, "J");
	JNI_LOAD_METHODID(env, clazz, NativeTest, onResult, "(I)V");
    DELETE_LOCAL_REF(env, clazz);
}

static void native_setup(JNIEnv* env, jobject thiz)
{
    NativeTest* nt = new NativeTest();
    nt->bind(env, thiz);
}

static void native_release(JNIEnv* env, jobject thiz)
{
    jlong handle = env->GetLongField(thiz, JNI_FIELDID(NativeTest, mNativeHandle));
    NativeTest* nt = (NativeTest*)handle;
    if(nt != NULL)
    {
        nt->unbind(env);
        delete nt;
    }
}

static void native_test(JNIEnv* env, jobject thiz, jint value)
{
    jlong handle = env->GetLongField(thiz, JNI_FIELDID(NativeTest, mNativeHandle));
    NativeTest* nt = (NativeTest*)handle;
    if(nt != NULL)
    {
        nt->test(env, value);
    }
}

static JNINativeMethod gNativeFfmpegMethod[] =
{
    {"nativeClassInit", "()V",  (void*)nativeClassInit },
    {"native_setup",    "()V",  (void*)native_setup },
    {"native_release",  "()V",  (void*)native_release },
    {"native_test",     "(I)V",  (void*)native_test },
}



Android调用Jni返回自定义对象 Android调用Jni返回自定义对象 博客:http://blog.youkuaiyun.com/lowprofile_coding/article/details/39367323 立即下载

相关推荐

android jni 传递对象的demo

android jni 传递对象的demo,展示了如何在java与C之间传递对象。详细介绍见相关博客。

android jni 注册函数,使用Frida分析动态注册jni函数绑定流程

原标题:使用Frida分析动态注册jni函数绑定流程 本文为看雪论坛文章看雪论坛作者ID:无造本文为 看雪安卓高研3w班(7月班)优秀学员作品。下面先让我们来看看讲师对学员学习成果的点评,以及学员的学习心得吧!讲师点评在对app进行逆向分析过程中,jni函数往往是非常关键的。不管是jni函数地址的绑定,还是jni函数的调用和执行过程,都离不开ART的支持。得益于Android的开源,可以通过对源码...

weixin_36473811的博客 631

LC整流滤波电路DIY:电感电容配合,手把手搭建低纹波直流电源

在直流电源设计中,整流滤波是连接交流输入与稳定输出的关键环节。常见的电容滤波虽然简单,但在大负载下纹波抑制能力有限,电感抵抗电流突变、电容抵抗电压突变,二者组合构成的LC滤波能有效降低输出电压纹波,同时减小开机浪涌电流。在工频线性电源、功放电源等对噪声敏感的场景中,LC滤波常作为稳压前的平滑缓冲。本文以一套完整DIY项目为线索,介绍整流桥后串联功率电感、并联滤波电容的电路构成,结合实际计算与波形测试,讨论电感量估算、电容选取、谐振风险、饱和电流等工程问题,并给出上电测试和故障排查方法。通过搭建与调试,可直观

weixin_29168813的博客 375

JNI绑定实践

目录背景静态注册1.引入so文件和native方法2.编译生成jni头文件3.实现jni方法4.实现CMakeLists.txt动态注册1.定义对应交互的java方法2.引入c++代码和CMakeLists.txt文件3.编辑c++文件4.实现CMakeLists.txt 背景 博主之前做的日志组件的结构是java和c++相结合实现。将日志的加密,压缩,文件写入等对性能比较敏感的模块放在c++层实现,而将日志的格式化,日志脱敏等功能放在java层实现。这就会涉及到java和c++的交互,即jni。 jni注

我是黄大仙 820

保姆级教程:用Qlib和LightGBM从零搭建你的第一个AI量化选股策略(附完整代码)

本文提供了一份详细的教程,教你如何使用Qlib和LightGBM从零搭建AI量化选股策略。教程涵盖了环境配置、数据获取、特征工程、模型训练和策略回测等关键步骤,并附有完整代码和常见问题解决方案,适合量化投资初学者快速上手。

weixin_29191081的博客 443

半导体制造中的通孔缺陷与冗余通孔技术解析

通孔(Via)是半导体制造中连接不同金属层的关键结构,其可靠性直接影响芯片良率。随着工艺节点演进至28nm及更先进制程,通孔缺陷导致的良率损失日益显著,主要表现为完全开路和高阻态两种失效模式。冗余通孔技术通过在关键位置增加备用连接,可有效提升芯片可靠性,其实现涉及物理冗余与电气冗余两种方案。该技术在7nm/5nm工艺中已证明可将通孔相关缺陷率降低10-100倍,但面临设计规则复杂性、规模处理效率和动态合规验证等工业化挑战。智能双切通孔插入流程通过动态DRC规则解析、奇偶层级并行处理和增量式验证等创新方法,显

weixin_35982453的博客 382

Android JNI ,将java 实例与c实例绑定

测试条件: c++ 中存在class TestA,其中含有属性int a。 java 中存在classTestJni, TestJni.java代码如下: 1 public class TestJni { 2 3 public native final void setA(int a); 4 public native final void add(i...

weixin_30360497的博客 133

手把手教你用DevExpress Patch工具解决VS项目中的试用弹窗问题

本文详细指导开发者使用DevExpress Patch工具解决Visual Studio项目中恼人的试用弹窗问题。核心在于理解并分步处理:首先正确应用补丁工具以绕过运行时验证,然后重点清理或重置项目中的licenses.licx文件以消除编译时验证,从而彻底根治弹窗。

weixin_29234423的博客 588

JAVA中JNI的简单使用

随时随地阅读更多技术实战干货,获取项目源码、学习资料,请关注源代码社区公众号(ydmsq666) 了解JNI:JAVA因其跨平台特性而受人们喜爱,也正因此,使得它和本机各种内部联系变得很少,所以JNI(Java Native Interface)就是用来解决JAVA本地操作的一种方式。JAVA通过JNI调用本地...

孤云博客 2676

Linear超高PSRR线性稳压器-典型应用电路解析

本文整理完了LT3045数据手册内所有的典型应用电路,试图让沉默的电路开口,简单介绍了他们这样做的目的和原理,从中我们可以更加熟悉这颗经典芯片的应用。但也有一些电路并没有搞懂,遗留下了不少问题。

硬件工程师笔记 2937

Vivado里LDPC IP核怎么配?手把手教你从6144bit数据到完整参数设置

本文详细介绍了在Vivado中配置LDPC IP核的完整流程,从6144bit数据的参数计算到实际IP核设置。通过分析基本图选择、扩展因子计算和移位参数确定等关键步骤,帮助工程师高效完成LDPC编译码的硬件实现,并提供了时序控制、仿真验证和性能优化的实用技巧。

weixin_30352645的博客 517

使用JNI总结

使用JNI总结和参考

GeiGe123的博客 929

单片机毕业设计-基于STM32单片机的智能镜系统-仿真设计

可通过MQ-2监测当前烟雾浓度可通过温湿度传感器监测当前温湿度可通过光照强度传感器监测光照强度可通过蜂鸣器进行烟雾报警可通过语音识别模块进行反馈播报状态可通过按键设置阈值三个继电器控制灯、加湿、风扇标签:STM32单片机、OLED112864、DHT11、BH1750、继电器、SU-03T、MQ-2、蜂鸣器题目扩展:智能家居安防、智能大棚控制系统、智能环境检测系统项目编号:ZL-32-240604-FZ。

bsdog11的博客 964

JNI c++对象与java对象互关联

android中如果需要调用c++代码需要写jni将java操作转接到c++代码中.但是大部分的文章都只是通过讲解通过  extern "C" 代码来访问具体功能.   在这里我要讲一种更方便的方法将java对象和c++对象互相绑定起来.      第一步:     JNIObject.java:public class JNIObject { protected long mObj

ab7936573的专栏 1808

华为OD机考双机位C卷 - 文件存储系统的排序(Java & Python & JS & GO & C++ & C)

华为OD机考双机位C卷 - 文件存储系统的排序, 提供Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。

算法大师! 777

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Android JNI 语法全解析:从基础到实战

摘要: JNI(Java Native Interface)是Android开发中连接Java与C/C++的关键技术,适用于音视频处理、硬件交互等高性能场景。本文系统讲解了JNI的核心概念、数据类型映射、方法注册(静态与动态)、内存管理(局部/全局引用)及常见操作(字符串、数组、对象交互)。重点分析了内存泄漏的预防策略(如及时释放引用)和调试技巧(日志与断点)。通过平衡性能与安全,开发者可高效利用JNI优化关键模块,同时避免崩溃和泄漏风险。掌握JNI能显著提升Android应用的底层能力,但需遵循“最小化使

weixin_37794278的博客 1288

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Bootstrap Icons 的 Capslock fill 图标:SVG 结构、字体与 Codepoint 使用指南

> 本文聚焦 Bootstrap Icons(官方开源 SVG 图标库)中 `capslock-fill`(大小写锁定填充)图标的完整使用方案,涵盖其 SVG 源码结构、与 `capslock` 描边版的关系、图标字体类名、Unicode 码点,以及内联 SVG、icon font、symbol sprite 三种接入方式。读完你将能够在 Bootstrap 5、纯 HTML 或任意前端框架中正确

gitblog_00505的博客 647

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Android NDK使用指南(进阶篇二)

中,介绍了JNI的工作流程及其中的核心部分代码的详细解释,接下来将介绍一些常用的使用技巧,帮助开发人员提高开发效率和代码质量。

weixin_46056189的博客 493

Android-NDK开发之基础--Android JNI开发高级篇(JNI中的常用方法)

转自:http://www.android123.com.cn/androidkaifa/683.html   有关Android JNI开发中比较强大和有用的功能就是从JNI层创建、构造Java的类或执行Java层的方法获取属性等操作。     一、类的相关操作     1. jclass FindClass(JNIEnv *env, const char *name);  查找类

158

network android,Network Class

Network ClassDefinitionAssembly:Mono.Android.dllIdentifies a Network.In this article[Android.Runtime.Register("android/net/Network", ApiSince=21, DoNotGenerateAcw=true)]public class Network : Java.Lan...

weixin_39881859的博客 156

pthread线程传递数据回主线程_Android多线程入门-线程基础

本文旨在对Android中的多线程做一个简单阐述0.虚拟机的本质在开始讨论之前,我们需要明确一下什么是虚拟机。虚拟机顾名思义,是一个可以模拟硬件的程序。虚拟机模拟的硬件包括但不限于:CPU,加法器,寄存器,函数栈。当我们有一一个虚拟机A,和一段程序B的时候,B的运行过程如下:首先启动虚拟机A(Java里面可以理解为一个C++程序)然后A加载B的代码文件,把代码文件解析为指令,这些指令一般都是自定义...

weixin_39928768的博客 284

相机预览时候camera的获取

参照 Android Camera 流程学习记录(四)—— Camera.startPreview() flow_小石不识月,呼作白玉盘。-优快云博客 相机预览的关键方法 static void android_hardware_Camera_startPreview(JNIEnv *env, jobject thiz) { ALOGV("startPreview"); sp<Camera> camera = get_native_camera(env, thiz,...

转载和创作优秀的博客 613

Android NDK学习笔记1-基础知识篇

引言 最近开发项目用到了多个C语言编写的动态链接库so,期间遇到很多问题,项目开发完毕后,我觉得有必要把开发中的一些知识点总结下来,并结合我手边的一本经典教程《Pro Android C++ with the NDK》,写下这个系列的文章,分享给大家,希望给想入门A...

125

Android Runtime JNI函数查找与绑定过程原理剖析(69)

JNI(Java Native Interface)作为Java与本地代码(如C/C++)交互的桥梁,在Android Runtime(ART)中承担着关键作用。通过JNI,Java代码能够调用本地代码实现的功能,本地代码也可以回调Java方法,极大地拓展了Android应用的能力边界,例如实现高性能的音视频处理、访问底层硬件资源等。

Android开发领域创作者 901

Android之 JNI详解

Android JNI详解

qq_29848853的博客 6442

Android 如何理解 Java JNI 中的引用与 Java 对象应用的区别

Java JNI 中的引用是 ​​本地代码与 JVM 对象交互的句柄​​,其本质是对元数据或对象访问权限的封装,允许在对象实例化前初始化(如类元数据);而 Java 中的对象引用是 ​​直接指向堆内存的实例指针​​,必须在对象创建后生效。理解两者的区别,有助于避免 JNI 开发中的内存泄漏和性能问题。

fukaiqiang 677
上一篇: C++类函数深入理解
下一篇: c语言小代码——对齐
code09
博客等级 码龄18年 31粉丝 56原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值