【Android】通过Profiling工具和adb确定app被系统杀死的原因

news2024/12/25 13:00:47

当您想要确定安卓App被系统杀死的原因时,可以通过以下步骤进行分析:

  1. 打开Android Studio中的Profiling工具
    在这里插入图片描述

在您的项目中,打开Android Studio并进入Profiling工具。点击左上角的“Android Profiler”图标,选择“CPU”或“Memory”,使其显示应用程序的性能指标,在顶部的时间轴上可以看到应用程序的各个时间段的信息。

  1. 找到应用程序被杀死的时间段

在Profiling工具中,查找被杀死应用程序的具体时间。
在这里插入图片描述

从时间轴上找到应用程序被杀死的时间段。

  1. 分析系统报告

在找到被杀死应用程序的时间段后,可以通过Adb命令查看系统报告,以获取更多详细信息。例如,在终端中使用以下命令:

adb shell dumpsys meminfo <package_name>

其中 <package_name> 是您的应用程序包名称。这将输出您的应用程序在系统内存中的使用情况。从输出中查找应用程序被终止的时间段并分析内存使用情况。如果应用程序在被终止之前消耗了大量内存,可能会因内存不足而被系统终止。

  1. 检查日志

使用以下命令在Adb控制台中查看日志信息:

adb logcat -d *:E

这将打印所有的错误日志。查找您的应用程序被终止的时间段的日志。这样可以了解应用程序的哪些部分可能出现了问题。还可以在日志中查找对象分配和释放的详细信息,并确定是否有意外的长时间超时或阻止等问题。
在这里插入图片描述
如图,左侧是app运行被杀死前最后一条错误日志

2023-06-04 07:07:52.512 10156-10156/com.iot.listeninsoul 
E/Toast: setGravity() shouldn't be called on text toasts, the values won't be used

右侧是系统在该app错误后的一条系统异常

06-04 07:07:52.512 10156 10156 
E Toast   : setGravity() shouldn't be called on text toasts, the values won't be used
06-04 07:07:52.564   428 13128 
E BpBinder: Too many binder proxy objects sent to uid 1000 from uid 10127 (6000 proxies held)

至此我找到了app被系统杀死的原因向系统进程(uid 1000)发送了超过6000个binder代理对象。


错误解决

在Android系统中,Binder是一种用于进程间通信(IPC)的机制。应用程序可以使用Binder在不同的进程之间进行通信。在某些情况下,由于使用不当,可能会导致系统输出错误日志"Too many binder proxy objects sent to uid xxx from uid yyy (zzz proxies held)",其中xxx和yyy为应用程序的UID和调用者的UID,zzz表示当前UID持有的Binder代理对象的数量。

这个错误日志的意思是,应用程序通过Binder机制向系统发送了太多的Binder代理对象,而这些代理对象导致系统的Binder进程(包括system_server等)消耗过多的内存和CPU资源。

造成这种错误日志的原因有很多,可能是应用程序在使用Binder时没有正确地释放它们,也可能是应用程序在使用Binder时使用了大量的回调和监听器,导致系统创建了大量的Binder代理对象并占用过多的系统资源。

解决这个问题的方法包括:

  1. 根据错误日志所提供的UID信息,定位和修复导致问题的应用程序。

  2. 在应用程序中使用Binder代理对象时,需要注意及时释放它们,以便避免过多的代理对象占用系统资源。可以使用try-finally块在释放代理对象时确保一定会被释放,例如:

IBinder binderProxy = null;
try {
    binderProxy = getBinderProxyObject();
    // 使用binderProxy对象
} finally {
    if (binderProxy != null) {
        binderProxy.unlinkToDeath(deathRecipient, 0);
        binderProxy = null;
    }
}
  1. 避免在应用程序中频繁使用回调和监听器,减少创建大量的Binder代理对象。

  2. 在应用程序的Manifest文件中,可以添加android:process属性,将服务或应用程序部分进程化,从而减少应用程序对系统资源的占用。

综上,遵循最佳实践和使用正确的代码约定可以帮助避免出现"Too many binder proxy objects sent to uid xxx from uid yyy (zzz proxies held)"的错误日志,并提高应用程序的性能和稳定性。


安卓UID 1000

在Android系统中,UID(User ID)是用于识别不同应用程序和进程之间的关键标识符。UID分为两类,系统UID和普通UID。系统中默认的UID为1000,是一个系统级别的UID,对应的是根用户(root)或系统管理员用户(system),它们可以执行一些非常重要的系统操作,并拥有系统内核和实现上的特殊权限。在Android系统中,UID为1000的进程因此是指系统进程,如:

  1. System_server进程:是Android系统的核心进程,负责管理各种系统服务,如包管理、窗口管理、电源管理、软件更新等。这个进程应该是运行时间最久的进程之一,也是最重要的系统进程之一。

  2. Mediaserver进程:是Android系统中负责处理音视频相关的服务的进程,例如解码、编码、格式转换等服务。在Android 5.0及之前的版本中,这个进程是由系统UID为1000的用户组管理的。

  3. Surfaceflinger进程:是Android系统的显示层服务,负责在屏幕上显示图像、文字和其他类型的信息。它与其他组件,如Window Manager之间进行通信来显示和处理UI元素。

除了System_server、Mediaserver和Surfaceflinger进程之外,还有一些其他的系统进程也属于UID为1000的系统进程。这些系统进程都是非常重要的组件,它们控制着Android系统的核心部分,使用者无法直接操作,但却在Android系统中起着至关重要的作用。


Android 优化内存

在Android应用开发中,系统限制了每个应用程序在运行时所能够占用的内存大小。如果您的应用程序需要占用更多的内存,可以通过以下几种方法增加应用程序的可占用内存:

  1. 从Manifest中修改android:largeHeap属性

在应用程序的Manifest文件中,可以添加以下行来允许应用程序使用较大的堆空间:

<application
    android:largeHeap="true"
    ...>
    ...
</application>
  1. 使用JNI和本地代码管理内存

通过使用JNI和本地代码进行内存管理,可以更有效地分配和释放内存。通过JNI,在本地代码中动态分配内存,可以更灵活地控制内存分配,同时避免了Java对象的垃圾回收机制,从而改善了应用程序的内存使用。
JNI(Java Native Interface)是一个允许Java代码调用本地代码(如C或C ++)的桥梁。JNI提供了一个接口,允许Java代码直接调用本地函数。在本地代码中,可以使用malloc()等函数来动态分配内存。由于这些内存不是由Java的垃圾回收机制管理,因此需要手动释放内存,以避免内存泄漏等问题。

以下是一个使用JNI和本地代码来管理内存的简单示例:

Java代码:

// 声明native方法,调用本地代码
public native int[] getArray(int size);

// 在getArray方法中调用本地方法
public int[] getArray(int size) {
    return getArrayFromJNI(size);
}

// 加载本地库
static {
    System.loadLibrary("native-lib");
}

// 定义本地方法,使用C/C++代码分配内存
private native int[] getArrayFromJNI(int size);

C/C++代码:

JNIEXPORT jintArray JNICALL Java_com_example_memorydemo_MainActivity_getArrayFromJNI(JNIEnv *env, jobject obj, jint size) {
    // 调用C中动态分配内存的函数
    int* arr = (int*)malloc(size * sizeof(int));
    jintArray jArr = (*env)->NewIntArray(env, size);

    // 将本地分配的内存拷贝到Java堆内存中
    (*env)->SetIntArrayRegion(env, jArr, 0, size, arr);
    return jArr;
}

在上述示例中,Java代码调用了本地代码中的getArrayFromJNI方法,并传递了一个整数参数size。在本地代码中,使用malloc函数分配了一个整数数组,然后将整数数组拷贝到Java堆内存中,并使用NewIntArray函数返回一个整数数组对象的引用。

需要注意的是,由于在本地代码中手动分配了内存,因此需要手动释放该内存以避免内存泄漏。可以在Java代码中将此任务交给本地代码,使其释放内存。例如:

Java代码:

public native void freeArray(int[] arr);

public void freeArray(int[] arr) {
    freeArrayFromJNI(arr);
}

private native void freeArrayFromJNI(int[] arr);

C/C++代码:

JNIEXPORT void JNICALL Java_com_example_memorydemo_MainActivity_freeArrayFromJNI(JNIEnv *env, jobject obj, jintArray jArr) {
    // 获取Java数组大小并释放本地代码中的内存
    int size = (*env)->GetArrayLength(env, jArr);
    int* arr = (int*) (*env)->GetIntArrayElements(env, jArr, NULL);
    free(arr);

    // 释放Java层的内存
    (*env)->ReleaseIntArrayElements(env, jArr, arr, NULL);
}

在本示例中,释放本地代码中的内存和Java层的内存分别在本地代码中处理。在freeArray方法中,Java代码调用freeArrayFromJNI并传递整数数组的引用。本地代码中,使用GetIntArrayElementsReleaseIntArrayElements函数分配和释放Java层的内存,然后使用free函数释放本地代码中分配的内存。

通过使用JNI和本地代码管理内存,可以更精细地控制内存分配和释放,并避免Java的垃圾回收机制所带来的性能开销。

  1. 使用LRU缓存等缓存技术优化内存

通过使用LRU缓存等缓存技术,可以优化应用程序的内存使用。通过缓存技术,可以将常用的对象保存在内存中,减少对象的创建和销毁,从而降低内存使用。
使用缓存技术可以减少对象的创建和销毁,从而优化内存使用。其中,LRU(Least Recently Used)缓存是一种常用的缓存技术,它通过保存最近最少使用的对象,以优化内存使用。

以下是一个使用LRU缓存技术优化内存的示例:

public class LruCacheDemo {
    private LruCache<String, Bitmap> cache;

    public LruCacheDemo() {
        final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
        final int cacheSize = maxMemory / 8; // 缓存大小为最大内存的1/8

        // 初始化LRU缓存,并重写sizeOf方法来计算缓存项目的大小
        cache = new LruCache<String, Bitmap>(cacheSize) {
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getByteCount() / 1024; // 像素数量转为KB
            }
        };
    }

    public void addBitmapToCache(String key, Bitmap bitmap) {
        if (getBitmapFromCache(key) == null) {
            cache.put(key, bitmap);
        }
    }

    public Bitmap getBitmapFromCache(String key) {
        return cache.get(key);
    }
}

在上述示例中,使用了LruCache类来实现LRU缓存。在构造函数中,根据最大内存大小计算出LRU缓存的大小,并重写了sizeOf方法来计算缓存项目的大小。

addBitmapToCache方法中,如果缓存中不存在指定的key,则将该图像添加到缓存中。在getBitmapFromCache方法中,根据key从缓存中获取相应的位图。

使用这种LRU缓存技术,可以避免重复加载已经存在的图片,减少了内存的使用,提高了应用程序的性能。

需要注意的是,LRU缓存技术并不适用于所有类型的应用程序,对于一些内存消耗很小的应用程序来说,LRU缓存技术的开销可能会超过收益。因此,在使用LRU缓存技术时,需要根据应用程序的实际情况进行调整。

  1. 优化应用程序的代码和资源

通过优化应用程序的代码和资源,可以减少应用程序的内存使用,从而达到增加可占用内存的目的。例如,移除不必要的资源、优化图片资源等。

需要注意的是,要合理使用内存的同时避免内存泄漏,否则会导致OOM(Out Of Memory)错误。应用程序的内存增加不表示应该浪费内存,而是应该在其使用场景中合理地利用内存。

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

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

相关文章

【Linux】Linux编译器 gcc/g++的使用初识动静态链接库

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;Linux &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 上一篇博客&#xff1a;【Linux】…

chatgpt赋能python:Python处理DICOM文件

Python处理DICOM文件 DICOM (Digital Imaging and Communications in Medicine)是医疗图像和数据的标准&#xff0c;用于存储和交换医学图像和相关信息。在医疗领域中&#xff0c;DICOM文件是医生和医学技师进行诊断和治疗的必要条件。在本文中&#xff0c;我们将介绍如何使用…

Linux下配置Qt6安卓开发环境

安装JDK 选择自己定义JDK安装路径 点击如下图按钮 安装SDK 提示TLS初始化失败 由于HTTPS问题造成无法下载,暂用Android Studio来安装Android SDK 成功安装SDK 安装NDK与命令行工具 正在下载NDK及命令行工具 NDK与工具下载完成 配置QT的Android SDK路径 配置NDK路径 选择ND…

Nginx服务性能和安全优化(念念不忘,必没回响)

一、配置Nginx隐藏版本相关信息 1.隐藏版本号 修改 nginx.conf 文件&#xff0c;在http块中添加字段后&#xff0c;重载服务 获取报文信息并查看&#xff08;浏览器查看或使用命令&#xff09; 2.修改版本号及相关信息 如果做了上一步在nginx.conf 中添加了 server_tokens…

数据结构-二分查找

1.1 什么是算法&#xff1f; 定义 在数学和计算机科学领域&#xff0c;算法是一系列有限的严谨指令&#xff0c;通常用于解决一类特定问题或执行计算 In mathematics and computer science, an algorithm (/ˈlɡərɪəm/) is a finite sequence of rigorous instructions, …

【Spring Cloud Gateway】⑥SpringBoot3.x集成SpringDoc指南

文章目录 背景本地开发环境介绍pom.xml主要依赖application.yml效果预览动态生成swagger文档分组效果预览在线文档 背景 Spring Cloud Gateway使用Netty作为嵌入式服务器&#xff0c;并基于响应式Spring WebFlux。做为微服务网关&#xff0c;多个微服务把API挂在Gateway上&…

轻量实时操作系统学习(二)

306xH系列架构 主系统包含以下部件&#xff1a; maters&#xff1a;RISC-V CPU、DMA、CORESIGHTslaves&#xff1a;嵌入式SYSRAM、嵌入式Flash memory、系统外设 这些模块通过AMBA总线架构互连&#xff0c;如图所示。 TCM_BUS&#xff1a;此总线将RISC-V CPU的TCM接口与存…

STM32学习(十四)

低功耗 降低集成电路的能量消耗。 低功耗特性对用电池供电的产品&#xff1a; 更小电池体积&#xff08;降低了大小和成本&#xff09; 延长电池寿命 电磁干扰更小&#xff0c;提高无线通信质量 电源设计更简单&#xff0c;无需过多考虑散热问题 STM32具有运行、睡眠、停止和…

【SQL Server】数据库开发指南(八)高级数据处理技术 MS-SQL 事务、异常和游标的深入研究

本系列博文还在更新中&#xff0c;收录在专栏&#xff1a;#MS-SQL Server 专栏中。 本系列文章列表如下&#xff1a; 【SQL Server】 Linux 运维下对 SQL Server 进行安装、升级、回滚、卸载操作 【SQL Server】数据库开发指南&#xff08;一&#xff09;数据库设计 【SQL Se…

Flutter 笔记 | Flutter 核心原理(七)The key is the key!

题外话 本文这个标题其实让我想起了电影《蝙蝠侠大战超人&#xff1a;正义黎明》中的一句话&#xff0c;在该片中&#xff0c;从未来穿越回来的闪电侠对蝙蝠侠发出警告&#xff1a; It’s Lois&#xff01; She’s the key&#xff01; 【布鲁斯&#xff0c;是露易丝&#xff…

chatgpt赋能python:Python增量备份:保障数据安全,提高效率

Python增量备份&#xff1a;保障数据安全&#xff0c;提高效率 现今&#xff0c;越来越多的企业和个人都需要使用计算机存储数据&#xff0c;这些数据可能是各种各样的&#xff0c;例如文件、数据库、邮件等等&#xff0c;这些数据的安全保障是至关重要的。 正是基于这样的背…

chatgpt赋能python:Python多行转一行:最简便的方法

Python多行转一行&#xff1a;最简便的方法 Python是一个既神奇又神奇&#xff08;fully magical&#xff09;的编程语言。但有时候&#xff0c;我们用Python编写的程序会产生多行代码&#xff0c;而需要把这些多行代码转换为一行以便于复制和粘贴。这种情况下&#xff0c;我们…

chatgpt赋能python:Python备份数据库——保障数据安全,防止数据丢失

Python备份数据库——保障数据安全&#xff0c;防止数据丢失 在现代社会&#xff0c;数据被称为新的石油&#xff0c;数据的意义愈发重要。数据的丢失可能会导致不可挽回的损失,给企业造成巨大的财务损失&#xff0c;更为重要的是企业形象的损失。备份数据是保护数据最好的途径…

chatgpt赋能python:Python奇偶求和函数

Python奇偶求和函数 Python是一种简单易学、高效的编程语言&#xff0c;具有丰富的库和工具&#xff0c;让程序员能够快速编写出各种各样的应用程序。Python中的函数可以让程序更加模块化&#xff0c;更加易于维护和扩展。其中&#xff0c;奇偶求和函数是一个很好的例子&#…

chatgpt赋能python:Python培训:成为一名高薪Python工程师

Python培训&#xff1a;成为一名高薪Python工程师 Python已成为当今最流行的编程语言之一&#xff0c;它广泛应用于人工智能、机器学习、数据科学和Web开发等各个领域。许多公司都在寻找经验丰富的Python工程师来开发他们的产品。如果你想成为一名高薪Python工程师&#xff0c…

创客匠人CEO蒋洪波:用门店思维做直播

互联网时代&#xff0c;转型线上做知识付费成为教育培训行业的主流&#xff0c;直播教学成为新型的教学模式受到了广泛认可。很多老师在线下培训深耕多年&#xff0c;知识储备丰富&#xff0c;但想要转型线上又缺少方法&#xff0c;缺少去改变的欲望&#xff0c;怕转型做线上直…

区块链的基本介绍

目录 1、简介 2、区块链的分类 2.1 公有链 2.2 联盟链 2.3 私有链 3、区块链特征 4、区块链结构 5、区块链对记账权利的分配方式 5.1 POW 5.2 PoS 5.3 DPoS 6、Defi、NFT、 gameFi 7、DAPP 7.1 DAPP 的核心要素 8、比特币 8.1 比特币简介 8.2 比特币数字签名…

白话ES搜索相关性问题

之前使用es&#xff0c;更多的是使用term查询&#xff0c;和agg聚合分析。对相关性关注较少。实际上es擅长的是做模糊搜索&#xff0c;相关性搜索。 ES是一个开源的通用的检索工具&#xff0c;能满足百分之八十的需求。相关性这个问题&#xff0c;是一个非常有意思的问题&#…

卡尔曼滤波与组合导航原理笔记(一) 第一部分 滤波的基本概念、递推最小二乘

文章目录 一、滤波的基本概念1、传统数字滤波器2、现代控制中的状态观测器3、最优估计的含义4、温度估计的例子1.问题描述2.分析 二、递推最小二乘 课程链接&#xff1a;https://www.bilibili.com/video/BV11K411J7gp/?p1 参考书目&#xff1a;《捷联惯导算法与组合导航原理》…

搭建本地MQTT服务器实现局域网通信

在这里mqtt就不多做介绍了直接上手怎么搭建本地服务器 一-. 我们先下载一个emqx&#xff0c;我们可以去官网下载免费的 https://www.emqx.io/https://www.emqx.io/ 下载完成之后我们打开这个文件夹 然后进入bin目录在左上角输入cmd然后回车 如果操作成功会来到这个界面 在这…