应用程序框架层 Android平台最常用的组件和服务都在这一层,是每个Android开发者必须熟悉和掌握的一层,是应用开发的基础。...最后需要将for里面生成的jintArray及时移除引用。创建的jintArray是一个JNI局部引用,如果局部引用太多的话,会造成JNI引用表溢出。...对于这类错误问题是非常不好排查的,比如内存地址访问错误、使用野指针、内存泄露、堆栈溢出等native错误都会导致APP崩溃。 虽然这些NDK错误不好排查,但是我们在NDK错误发生后也不是毫无办法可言。...在使用JNI时,由于本地代码不能直接通过引用操作JVM内部的数据结构,要进行这些操作必须调用相应的JNI接口间接操作JVM内部的数据内容。...不然局部引用会越来越多,最终导致崩溃(在Android低版本上局部引用表的最大数量有限制,是512个,超过则会崩溃)。
摘抄自Android 进阶解密>>一书 JNI 是什么 JNI是Java Native Interface的缩写, 译为本地接口,是Java与其他语言通信的桥梁。...、全局引用与弱引用比较 和Java引用类型一样,JNI也有引用类型,分别是,本地引用、全局引用与弱引用 局部引用 局部引用:通过NewLocalRef和各种JNI接口创建(FindClass、NewObject...:JNIEnv提供函数所返回的引用基本上都是本地引用 特点: 当native函数返回,它就会自动释放 只能在创建它的线程有效,不能够跨线程使用 局部引用是JVM负责的引用类型,受JVM管理 Android...中局部引用表最大数量为512个,如果超过这个表最大容量限制,就会造成局部引用表溢出,程序崩溃,所以不需要用局部引用时候要调用DeleteLocalRef立即删除。...JNI规范指出,任何实现JNI规范的JVM,必须确保每个本地函数至少可以创建16个局部引用(可以理解为虚拟机默认支持创建16个局部引用)。 局部引用不能跨线程使用,只在创建它的线程有效。
线程溢出 不同的手机允许的最大线程数量是不一样的,在有些手机上这个值被修改的非常低,就会比较容易出现线程溢出的问题 FD数量溢出 文件描述符溢出,当程序打开或者新建一个文件的时候,系统会返回一个索引值,...指向该进程打开文件的记录表,例如当我们用输出流文件打开文件的时候,系统就会返回我们一个FD,FD是可能出现泄露的,例如输入输出流没有关闭的时候,详细可参考 Android FD泄露问题 虚拟内存不足 在新建线程的时候...如果太大就会影响到可创建栈的数量,如果是多线程应用,就会导致内存溢出。 本地方法栈 与 java 栈的效果基本类似,区别只不过是用来服务于 native 方法。...#单个应用程序最大内存限制,超过将被Kill, dalvik.vm.heapsize=256m #所有情况下(包括设置android:largeHeap="true"的情形)的最大堆内存值,超过直接...Env 和 创建线程 创建 JNI Env 失败 FD 溢出导致 JNIEnv 创建失败 E/art: ashmem_create_region failed for 'indirect ref table
#### 线程溢出 不同的手机允许的最大线程数量是不一样的,在有些手机上这个值被修改的非常低,就会比较容易出现线程溢出的问题 #### FD数量溢出 文件描述符溢出,当程序打开或者新建一个文件的时候,系统会返回一个索引值...,指向该进程打开文件的记录表,例如当我们用输出流文件打开文件的时候,系统就会返回我们一个FD,FD是可能出现泄露的,例如输入输出流没有关闭的时候,[详细可参考 Android FD泄露问题](https...如果太大就会影响到可创建栈的数量,如果是多线程应用,就会导致内存溢出。 - 本地方法栈 与 java 栈的效果基本类似,区别只不过是用来服务于 native 方法。...=48m #单个应用程序最大内存限制,超过将被Kill, dalvik.vm.heapsize=256m #所有情况下(包括设置android:largeHeap="true"的情形)的最大堆内存值...; } stack_size += 1 * MB; if (kMemoryToolIsAvailable) { stack_size = std::max
从github上获取android-ndk-android-mk,进入hello-jni工程。...+实现JNI 遇到错误: Error:Execution failed for task ‘:app:compileDebugNdk’....NDK本地对象数量溢出问题 Local ref table overflow NDK本地只允许持有512个本地对象,return后会销毁这些对象。必须注意,在循环中创建的本地对象要在使用后销毁掉。...如果未经任何处理,会出现无引用错误 error: undefined reference to '...... 因此在C++文件中涉及到C方法,需要声明。.../log.h> #define LOG_TAG "rustApp" __android_log_write(ANDROID_LOG_VERBOSE, LOG_TAG, "My Log"); 此时编译出现了错误
首先,配置Android.mk文件,如下所示 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hello-jni...,如: public static native String getHelloString(); 接着,Android Studio可以帮助我们构建hello-jni.c文件,在错误的地方,alt+...enter后,就会发现多了一个hello-jni.c文件,里面需要引用的文件和声明的函数头,as都帮我们做好了,我们只需要写好函数体就好,这功能真的非常贴心,我们开发只用关心业务逻辑即可。...的c代码中需要注意,可以运行时会报如下错误 JNI ERROR (app bug): local reference table overflow (max=512) 这是JNI对java对象引用的限制...java对象后及时调用env->DeleteLocalRef方法手动释放本地引用 如果native method返回java对象就不需要手动release,因为java会自动回收 好了,NDK开发的基础就讲到这里吧
【三 间接引用表】 JNI实现源码分析【四 函数调用】 JNI实现源码分析【五 结束语】 正文 在JNI实现源码分析【二 数据结构】的参数传递一节中,我们提到,JNI为了安全性的考虑使用了形如jobject...JNI API中的全局引用和局部引用,指的就是全局作用域的间接引用表和线程作用域的间接引用表。...这里顺便提一下,当超过这个最大时,就会报local reference table overflow (max=512)的错误。...那么,这里就有一个问题了,既然间接引用和间接引用表有关,那在使用JNI的API时,获取到这些间接引用时,JNI将真实的对象保存在哪个表里面?...(max=512)。
在JNI层进行性能优化和防止内存泄漏是Android NDK开发的核心挑战之一。以下是我在实践中总结的关键策略和最佳实践。...手动释放:在以下场景必须手动释放 (env->DeleteLocalRef(localRef)):创建大量局部引用(如在循环中创建对象),避免超出JVM规定的局部引用表容量(通常512-1024)。...使用智能指针 (C++):std::unique_ptr, std::shared_ptr 结合自定义删除器(如free, delete[], 特定库的释放函数)能极大减少手动内存管理错误。...六、工具链与调试1、内存泄漏检测:AddressSanitizer (ASan):Android NDK r21+ 默认支持。检测堆栈溢出、use-after-free、内存泄漏等。...Android Studio Profiler (Memory Profiler):追踪Java堆和Native堆分配。捕获堆转储,分析对象引用链。
字符串函数返回jchar *或jbyte *,它们是C样式的指向原始数据的指针,而不是本地引用。它们被保证有效,直到调用Release,这意味着当native方法返回时它们不会自动释放。...扩展检查 JNI几乎没有错误检查,错误通常会导致崩溃。Android提供了一种称为CheckJNI的模式,在调用标准实现之前,将JavaVM和JNIEnv函数表指针切换到执行扩展系列检查的函数表。...References:使用DeleteGlobalRef/DeleteLocalRef时,用了错误的引用。...在这种情况下,你能在下次应用程序启动时在logcat输出中看到下面的信息: D Late-enabling CheckJNI 您还可以在应用程序的manifest中设置android:debuggable...如果您的应用程序代码正在加载库,FindClass将使用正确的类加载器。 将类的实例传递到需要它的函数中,通过声明本地方法来接受Class参数,然后传递Foo.class。
近期在编程中遇到一个内存溢出的BUG,考虑到这是个新手常见问题,特记录如下。Java应用程序开发过程中,内存溢出(OutOfMemoryError,简称OOM)是开发者经常遇到的问题。...:错误类型是Java heap space,即堆内存空间不足错误发生在HeapOutOfMemoryDemo类的OOMObject内部类的构造函数中最终触发错误的是main方法中的代码2.2 问题原因分析堆内存溢出的根本原因是应用程序试图使用的内存量超过了...最佳实践和预防措施6.1 合理设置JVM参数根据应用程序的实际需求合理设置堆内存大小:# 设置初始堆内存为512MB,最大堆内存为2GBjava -Xms512m -Xmx2g MyApp# 启用堆转储以便分析...WeakReference cacheRef = new WeakReference(cache);引用类型对比表:引用类型对比:┌─────────────┬────────────...,不仅要关注表面的错误信息,更要深入分析应用程序的内存使用模式,从根本上优化代码和架构设计。
Java Native Interface(JNI)是一个强大的机制,允许Java代码与其他语言编写的应用程序或库(主要是C和C++)进行交互。...正确的做法是在本地代码中检查潜在错误,并通过JNI接口抛出Java异常,让Java层能够捕获并处理。 例如,如果本地方法发现无法打开指定的文件,它应该抛出一个IOException给Java层。...这要求在C/C++代码中检测错误,并通过JNI函数手动创建并抛出异常。...安全问题 潜在风险:使用JNI时,最大的安全风险包括缓冲区溢出和未经验证的输入。...)而不是全局引用(Global References),除非需要跨多个 JNI 调用保持引用。
概述 如果你是OpenCV框架做开发、特别是用OpenCV C++版本或者Java/Android版本JNI的调用的化,可能很多时候你遇到最棘手的问题就是程序运行会越来越慢,甚至死机了,原因很简单,有时候你有内存泄漏问题...最典型的就是Mat对象的release方法,调用release并不会重根本上保证立刻回收内存,它只是让对象的引用计数减一,只有当对象的引用计数为0的时候,才会回收内存。...滥用/重用变量导致内存泄漏 注意要避免下面三种错误代码写法 错误一: Mat m1; for (int i = 0; i < 100; i++) { m1 = Mat::zeros(...Size(512, 512), CV_8UC3); } imshow("input-m1", m1); m1.release(); 错误方式:在循环中创建无数Mat对象,结果只释放了一个,很多人的循环就是这么写的...,OpenCV框架对内存的管理已经很智能化了,基本上代码规范写,记得release就不会有这个方面的问题,但是还是小心为妙,特别是跨语言调用的时候比如Android/Java通过JNI调用OpenCV函数
递归或死循环无限递归导致栈溢出(StackOverflowError)。...二、资源管理问题内存泄漏(Memory Leak)对象未及时释放(如 Android 中未注销监听器,iOS 中循环引用未用 weak 修饰)。...内存溢出(OOM, OutOfMemory)加载大图、缓存未清理或频繁创建对象导致内存不足。文件或数据库操作错误未关闭数据库连接,文件读写权限问题,或操作已被删除的文件。...本地数据损坏读取损坏的 SharedPreferences、数据库或缓存文件。应用状态不一致后台返回前台时数据未恢复,或 Activity/Fragment 生命周期管理不当。...JNI 错误(Android)Native 代码(C/C++)中的内存错误或未捕获异常。
性能陷阱 使用JNI的程序员面临的五大性能缺陷: 不缓存方法ID,字段ID和类 触发数组拷贝 返回而不是传递参数 在本地代码和Java代码之间选择了错误的边界 使用许多本地引用而不通知JVM 不缓存方法...数组越大,创建的本地引用就越多。 本地代码执行完成时,将自动释放这些本地引用。JNI规范要求每个本机能够创建至少16个本地引用。...JNI代码使用错误 JNI的五大使用错误: 错用 JNIEnv 不检查异常 不检查返回值 错误地使用数组方法 错误地使用全局引用 错用JNIEnv 子线程执行本地代码,尝试通过JNIEnv调用JNI...当本地调用JNI方法时,可能引发异常,这时候需要本地去检查异常,并采取适当的操作。常见的JNI编程错误是调用了JNI方法而不检查异常,并忽略异常继续执行。这可能导致严重的错误和崩溃。 ...当从本地方法返回时,它不仅没有被释放,而且应用程序再也没有办法获取它的引用以便以后释放它,因此该对象将永远存在。
* sizeof(IrtEntry); table_mem_map_.reset(MemMap::MapAnonymous(..., table_bytes, ...)); 这里的max_count是常量...art::kLocalsInitial == 512。...所以 table_bytes = 512 * 8 = 4096 = 4k,刚好是一个内存页的大小。 因此是调用MemMap::MapAnonymous() 失败了。...return 0; } 步骤2先按下不表,我们看看步骤1的逻辑: static int __allocate_thread(......Native 层的Stack Overflow检测 另外上面的代码片段1其实也挺有意思的,它优雅的判断了StackOverflow的场景,避免栈内存溢出污染其他内存区域。
只要应用引用非 SDK 接口或尝试使用反射或JNI来获取其(包括Method、Class、Field)句柄,这些限制就适用。...如果您的应用尝试访问其中任何一个接口,系统就会抛出错误 有条件屏蔽 (greylist-max-x) 从 Android 9(API 级别 28)开始,当有应用以该 API 级别为TargetVersion...SDK (whitelist) 已在 Android 框架中正式记录、受支持并且可以自由使用的接口 简单描述则为以下情况 : black List : 不管在哪个平台上 , 都会抛出错误 greylist-max-x...: 当APP的TargetVersion与运行时Android版本相同时 , 则会抛出错误 greylist : 目前可以继续调用 , 其实系统是不建议这样使用 , 可能在未来的版本会加入到greylist-max-x...image.png 接口访问 当black-list中接口通过反射、JNI接口去获取相应的Method、Field的引用时 , 就会报错.
通过 android的JNI调用支付宝脱机认证库本地接口时,我欲返回一个类的实例,但是却报了几个错,最后查出来了原因。在此总结下。...错误一 :E/dalvikvm﹕JNI ERROR (app bug): accessed stale local reference ,jclass is an invalid local reference...AllocObject 原因是 android的垃圾回收机制问题,新版本已经不允许全局使用findclass出来的局部引用了, 会被GC回收掉。...二,注意这个地方,用NewGlobalRef把引用设为全局的。写在 JNIEXPORT jint JNI_OnLoad(JavaVM* vm,void *reserved) 中。...,qrCodeOfByte, NULL); qrcode_len = (*env)->GetArrayLength(env,qrCodeOfByte); if(qrcode_len > 512
中的引用 在JNI中有三种引用:本地引用(LocalReference)、全局引用(GlobalReference)、弱全局引用(WeakGlobalReference)。...本地引用(LocalReference) 在JNI本地函数中生成的Java对象,它们的生命周期应该在函数退出时结束。 虚拟机如何保证呢?...每个Java线程都有一张本地引用(LocalReference)表,虚拟机在进行内存回收时不会回收表里的对象。...而在创建对象时,JNIEnv隐式地把这些Java对象加入到本地引用(LocalReference)表中了。 本地函数执行完后再将其从表中移除。这样虚拟机会在下次垃圾回收时将其释放。...JNI部分发生了错误,通常情况下不会打印太多的log。
JNI 全称 Java Native Interface。...本地方法的用途 本地方法主要提供三种用途: 提供“访问特定平台的机制”能力,如访问注册表(registry)和文件锁(file lock) 提供“访问遗留代码库”能力,进而访问遗留数据(legacy data...所以,使用了本地方法的应用程序也不可以避免受到内存毁坏导致的错误。...Java 是一门安全的语言(safe language),因为它对于缓冲区、数组越界、非法指针以及其他的内存破坏错误都自动免疫,而类似内存溢出或者指针异常等问题却始终困扰着C/C++这样的非安全语言。...其三,因为本地语言是平台相关,使用本地方法的应用程序也不再是“自由移植”的。 其四,使用了本地方法的应用程序使得代码调试变得困难,在进入和退出本地方法时,需要额外的固定开销。
错误,这也是Android中发生OOM的主要原因。...为了实现这个想法,我们使用了GOT表Hook技术(这里不展开介绍)。有了Hook手段,但是还没有找到合适的Hook点。...原始HPROF文件和裁剪后再恢复的HPROF文件分别在Android Studio中打开,发现裁剪再恢复的HPROF文件打开后,只是看不到对象中的基础数据类型值,而整个的结构、对象的分布以及引用链路等与原始.../proc/sys/kernel/threads-max规定了每个进程创建线程数目的上限。...在/proc/pid/limits描述着Linux系统对对应进程的限制,其中Max open files就代表可创建FD的最大数目。