Android | App内存优化 之 内存抖动解决实战

简介: Android | App内存优化 之 内存抖动解决实战
本文的精简总结在文首Pre文末小结以及解决技巧处!!!

Pre

  • 定义:内存频繁分配和回收导致内存不稳定
  • **明显特征:频繁GC、

Memory Profiler 内存分配图形曲线呈锯齿状
CPU ProfilerCall Chart 栏下 反复出现绿色条形**

  • 危害:导致卡顿、OOM

内存抖动导致OOM

  • **频繁创建对象,!!!!!

导致内存不足或者产生内存碎片!!!!!
内存碎片内存不连续,有 内存空洞
某两个正在使用的内存中间有一个间隔,
这个间隔虽然也被算在可用内存里面,
但实际上,因为它过小,
当我们申请内存的时候,经常是需要申请一定量的连续内存,
而这些碎片小内存不符合要求,是不能拿来使用的)**

  • 不连续的内存片无法被分配,可分配的内存不足,导致OOM;
  • 情况严重时会导致卡顿;随后可分配的内存减少,便可能导致OOM!!!

解决内存抖动实战

使用Memory Profile 排查处理

不同的工具,有自己适合的使用场景;

使用Memory Profile 初步排查

(后文中Memory Profile 简写成MP)

  • 图表直观,可以清晰地看到内存曲线;
开始编程
  • 布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/bt_memory"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="执行任务" />

</LinearLayout>
  • 对应的Activity文件:
/**
 * 模拟内存抖动的界面
 */
public class MemoryShakeActivity extends AppCompatActivity implements View.OnClickListener {

    @SuppressLint("HandlerLeak")
    private static Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            // 创造内存抖动(编写耗内存的操作)
            for (int index = 0; index <= 100; index++){
                String arg[] = new String[100000];
            }
            mHandler.sendEmptyMessageDelayed(0,30);
        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_memory);
        findViewById(R.id.bt_memory).setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        mHandler.sendEmptyMessage(0);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mHandler.removeCallbacksAndMessages(null);
    }
}
  • 运行:
  • 点击按钮前,MP图平稳:
  • 点击按钮后,开始出现锯齿状(真机调试可能锯齿状不会很明显):小米5s Plus真机调试Google Nexus_5X调试

这个时候,便可以判断,程序已经发生了内存抖动;

  • 情况严重时会导致卡顿;随后可分配的内存减少,便可能导致OOM!!!
  • **这个时候我们便从MP图锯齿状图形

观察到内存抖动的现象了,
接下来要开始分析,
内存抖动真正发生位置,是在哪里;**

  • **真正的项目中,一个Activity可能是有成百上千行代码,

那我们改如何知道哪里出了问题呢;**

  • 可以使用MP的堆转储按钮,继续进行分析:

**点击堆转储按钮,(或者直接在图中选中一段图形)
工具会弹出刚刚选中的一段时间内,
内存分配情况窗口
阅读时,可以点击下侧表格右上角的栏目项
进行对应项的排序,
如点击Allocations
分配情况表格会按照分配的实例个数进行排列:
我们可以看到锯齿的位置,String[]的分配是相对比较大的;
Shallow Size是该类型实例的总大小(以字节为单位);**

  • **于是现在可以锁定,String[]是最可疑的引起内存抖动的原因,

点击左边的String[]行项,工具会在右边,弹出另外一个窗口,
窗口上边是分配出来的该类型的所有实例(<工具右上>),
点击任意一个实例,
又会在下边弹出一个该实例的内存分配的堆栈信息<工具右下>——Allocation Call Stack),
信息即,这个实例占有的这块内存,是在哪里分配的:
我们可以看到,
MP工具的右下表格显示出来了右上角选中的对应的实例
分配内存的位置——
handlerMessage方法中,MemoryShakeActivity文件的第27行”;
右键之,选中Jump to Source
直接在IDE代码编辑界面,跳转追踪到,可疑诱因String[]创建源码处 / 位置!!
然后便发现原因,进行代码的修改!!**

或者也可以使用CPU Profiler 排查处理

**Call Chart 标签提供函数跟踪的图形表示形式,
其中,水平轴表示函数耗费的时间,垂直轴显示其被调用者。
对系统 API 的函数调用显示为橙色
应用自有函数调用显示为绿色
对第三方 API(包括 Java 语言 API)的函数调用显示为蓝色。**


参考文章:

  • **运行程序以及MP工具,

使用Record按钮开始记录某一段CPU执行的时间,
接着点击Stop停止对这段时间记录;
(上述Record记录完毕之后会在工具下侧弹出图表界面,
Call Chart ,依据这些图表数据)
跟踪这一段CPU执行的时间,
如果发现某一段(应用自有函数调用代码(即绿色的条形段)在反复地被执行,!!!!
(如下图的箭头所示)便是内存抖动的位置:!!!!
双击Call Chart中的一段绿色条形
可以直接在IDE代码编辑界面,跳转追踪到,可疑诱因String[]分配执行函数 源码处 / 位置!!
然后便发现原因,进行代码的修改!!**




小结

  • 使用Memory Profile 初步排查

该工具的图表显示方式非常直观,可以清楚地看到内存的使用情况;
可以很方便地发现 APP在使用过程中,
内存分配图形是不是一个锯齿状,有没有内存抖动的表现!

  • **使用Memory Profiler的堆转储 / 跟踪分配内存 功能

借助Instance View
追踪到分配内存较高/分配实例较多的实例类型
跟踪该实例类型的某几个具体实例 创建/分配 位置

(或者使用CPU Profiler,跟踪一段CPU执行的时间,
如果发现某一段应用自有函数调用代码
Call Chart 栏下的绿色条形反复地被执行,便是内存抖动的位置,
追踪这些绿色条形重复执行可疑函数位置),

然后结合代码进行排查,找到诱因位置;**




内存抖动的解决技巧

**重点关注:循环或者频繁调用的地方!!
因为内存抖动就是 内存在被不断地回收分配
这种情况的话经常是 出现在 循环或者频繁调用的地方**





参考自
相关文章
|
1月前
|
存储 前端开发 Java
Android MVVM架构模式下如何避免内存泄漏
Android采用MVVM架构开发项目,如何避免内存泄漏风险?怎样避免内存泄漏?
89 1
|
1月前
|
XML Java 数据库
安卓项目:app注册/登录界面设计
本文介绍了如何设计一个Android应用的注册/登录界面,包括布局文件的创建、登录和注册逻辑的实现,以及运行效果的展示。
140 0
安卓项目:app注册/登录界面设计
|
9天前
|
Android开发 开发者
Android性能优化——内存管理的艺术
Android性能优化——内存管理的艺术
|
1月前
|
编解码 Android开发 UED
构建高效Android应用:从内存优化到用户体验
【10月更文挑战第11天】本文探讨了如何通过内存优化和用户体验改进来构建高效的Android应用。介绍了使用弱引用来减少内存占用、懒加载资源以降低启动时内存消耗、利用Kotlin协程进行异步处理以保持UI流畅,以及采用响应式设计适配不同屏幕尺寸等具体技术手段。
49 2
|
1月前
|
存储 监控 算法
JVM调优深度剖析:内存模型、垃圾收集、工具与实战
【10月更文挑战第9天】在Java开发领域,Java虚拟机(JVM)的性能调优是构建高性能、高并发系统不可或缺的一部分。作为一名资深架构师,深入理解JVM的内存模型、垃圾收集机制、调优工具及其实现原理,对于提升系统的整体性能和稳定性至关重要。本文将深入探讨这些内容,并提供针对单机几十万并发系统的JVM调优策略和Java代码示例。
49 2
|
1月前
|
JavaScript 小程序 开发者
uni-app开发实战:利用Vue混入(mixin)实现微信小程序全局分享功能,一键发送给朋友、分享到朋友圈、复制链接
uni-app开发实战:利用Vue混入(mixin)实现微信小程序全局分享功能,一键发送给朋友、分享到朋友圈、复制链接
317 0
|
2月前
|
存储 开发工具 Android开发
使用.NET MAUI开发第一个安卓APP
【9月更文挑战第24天】使用.NET MAUI开发首个安卓APP需完成以下步骤:首先,安装Visual Studio 2022并勾选“.NET Multi-platform App UI development”工作负载;接着,安装Android SDK。然后,创建新项目时选择“.NET Multi-platform App (MAUI)”模板,并仅针对Android平台进行配置。了解项目结构,包括`.csproj`配置文件、`Properties`配置文件夹、平台特定代码及共享代码等。
161 2
|
1月前
|
安全 网络安全 Android开发
深度解析:利用Universal Links与Android App Links实现无缝网页至应用跳转的安全考量
【10月更文挑战第2天】在移动互联网时代,用户经常需要从网页无缝跳转到移动应用中。这种跳转不仅需要提供流畅的用户体验,还要确保安全性。本文将深入探讨如何利用Universal Links(仅限于iOS)和Android App Links技术实现这一目标,并分析其安全性。
224 0
|
2月前
|
XML 数据库 Android开发
10分钟手把手教你用Android手撸一个简易的个人记账App
该文章提供了使用Android Studio从零开始创建一个简单的个人记账应用的详细步骤,包括项目搭建、界面设计、数据库处理及各功能模块的实现方法。
|
1月前
|
JSON 小程序 JavaScript
uni-app开发微信小程序的报错[渲染层错误]排查及解决
uni-app开发微信小程序的报错[渲染层错误]排查及解决
479 7