6

手把手教你在Android Studio 3.0上分析内存泄漏

 2 years ago
source link: http://www.androidchina.net/7808.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
封面

戳我下载 Android Studio 3.0

这个不用梯子我会告诉你吗

1.写在前面

Google在上周发布了Android Studio 3.0的正式版本,周四早晨在上班的地铁上就看到群里在沸沸扬扬的讨论关于3.0版本的各种坑,啊,不对,各种特性,到公司之后就迫不及待的更新了3.0版本,嗯,还算顺利,只遇到了一个坑,一切都在happy的进行着。

什么,你以为我想要写遇到的坑是什么,呵呵哒,我才不会告诉你,等等。。。手里的板砖先放下,一会说还不行吗,今天我们主要来聊聊如何在Android Studio 3.0上分析内存泄漏,文章的内容很简单,但是自己摸索还是需要一些时间的,所以就在这里记录下来分享给大家。

2.强大的Android Profiler

戳这里查看官方文档

在3.0版本中,android使用了新的性能分析工具Android Profiler来代替原有的Android Monitor,使用方式和原来类似,都可以分析CPU、内存和网络的使用情况,但是功能强大了很多。

开始使用

还记得我之前写过一篇文章《Android 使用RxLifecycle解决RxJava内存泄漏》,本文将以这篇文章里的Demo为例,使用Android Studio 3.0再次分析一下内存泄漏。

首先点击工具栏中的Profile按钮将待分析的App安装到设备上,也可以直接安装,在AS底部选择Android Profiler按钮:

将待分析的APP安装到设备上

可以看到有下面的提示,大概意思是不能在当前进程进行更高级的分析:

不能在当前进程进行更高级的分析

点击Run Configuration进去看看,发现不能勾选开关,提示gradle插件版本太低,需要2.4以上版本才可以,嗯,那就更新一下:

更新gradle插件版本

已经更新到3.0版本了,可以勾选开关了,点击确定:

dependencies {
    classpath 'com.android.tools.build:gradle:3.0.0'
}
勾选开关

又来一个警告,大概意思是说,你的gradle版本已经升级到3.0了,需要和26.0.2版本的构建工具搭配才更好,好好好,听你的:

更新26.0.2版本的构建工具

更新完成之后,需要再次运行一下App,如果还提示不能进行更高级的分析,请重启Android Studio,重启还不好,没关系,反正今天也用不到它,不要打我,下面来看下正常的Android Profiler:

Android Profiler

点击MEMORY进入内存详情,在这里可以实时查看内存的占用情况:

内存详情

内存泄漏分析

我们先写个会发生内存泄漏的程序分析一下:

public class RxLifecycleComponentsActivity extends RxAppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rxlifecycle);
        ButterKnife.bind(this);

        initData();
    }

    private void initData() {
        // 每隔1s执行一次事件
        Observable.interval(1, TimeUnit.SECONDS)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Long>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {

                    }

                    @Override
                    public void onNext(@NonNull Long aLong) {
                        Log.i("接收数据", String.valueOf(aLong));
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }
}

很简单,每隔1s发送一条数据,因为关闭Activity之后没有取消订阅,RxJava还继续持有Activity的引用,所以在内存回收的时候,该Activity不会被回收,由此引发内存泄漏。

下面反复打开关闭页面5次,然后手动GC(点击左上角的垃圾桶图标),发现内存占用并没有减少:

内存泄漏分析

分析一下当前的内存堆栈情况(点击垃圾桶图标右侧的图标):

分析内存堆栈情况

选择按包名查找,找到当前测试的Activity,发现存在5个实例,由此可见,内存已经发生了泄漏:

内存泄漏

防止内存泄漏

修改一下上面的代码,在关闭Activity时取消订阅:

public class RxLifecycleComponentsActivity extends RxAppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rxlifecycle);
        ButterKnife.bind(this);

        initData();
    }

    private void initData() {
        // 每隔1s执行一次事件
        Observable.interval(1, TimeUnit.SECONDS)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .compose(this.<Long>bindUntilEvent(ActivityEvent.DESTROY))
                .subscribe(new Observer<Long>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {

                    }

                    @Override
                    public void onNext(@NonNull Long aLong) {
                        Log.i("接收数据", String.valueOf(aLong));
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }
}

反复打开页面5次,手动GC,看下当前的堆栈情况,可以看到当前已经没有RxLifecycleComponentsActivity的实例存在了:

无内存泄漏

OK,到这里,在Android Studio 3.0上分析内存泄漏就学习完了,赶快去动手试试吧!

3.更新Android Studio遇到的问题

编译的时候报错:

Error:(41, 0) Cannot set the value of read-only property 'outputFile' for ApkVariantOutputImpl_Decorated{apkData=Main{type=MAIN, fullName=debug, filters=[]}} of type com.android.build.gradle.internal.api.ApkVariantOutputImpl.

发现是在gradle里打包输出apk的代码出的问题,原代码是这样的:

applicationVariants.all { variant ->
    variant.outputs.each { output ->
        def file = output.outputFile
        String apkName = "APK_NAME" + defaultConfig.versionName.replace(".", "_") + ".apk"
        output.outputFile = new File(file.parent, apkName)
    }
}

修改成这样就可以了:

applicationVariants.all { variant ->
    variant.outputs.all {
        outputFileName = "APK_NAME" + defaultConfig.versionName.replace(".", "_") + ".apk"
    }
}

4.写在最后

戳我下载 Android Studio 3.0

戳我下载本文使用的测试Demo


Recommend

  • 125
    • zhuanlan.zhihu.com 6 years ago
    • Cache

    Web 应用内存分析与内存泄漏定位

    Web 应用内存分析与内存泄漏定位题注:阿里巴巴南京研发中心成立一年来业务与团队迅速扩展,诚求前端/后端等各路英才。欢迎关注 [阿里南京技术专刊] (https://zhuanla...

  • 104
    • 掘金 juejin.im 6 years ago
    • Cache

    内存分析与内存泄漏定位

    内存分析与内存泄漏定位是笔者现代 Web 开发工程化实践之调试技巧的一部分,主要介绍 Web 开发中需要了解的内存分析与内存泄露定位手段,本部分涉及的参考资料统一声明在Web 开发界面调试资料索引。 无论是分布式计算系统、服务端应用程序还是 iOS、Andr

  • 106
    • www.klion26.com 6 years ago
    • Cache

    Java 内存泄漏分析和对内存设置

    Java 内存泄漏分析和对内存设置

  • 48
    • 微信 mp.weixin.qq.com 5 years ago
    • Cache

    Kong 0.12.3 的一处内存泄漏分析

  • 53

    在flutter开发中,始终会有下面两个无法避免的问题: 原生项目往flutter迁移,就需要在原生项目中接入flutter flutter项目中要使用到一些比较成熟的应用,就无法避免去用到原生的各种成熟库,比如音视频之类的

  • 10

    Go程序内存泄漏的分析以及避免2016-10-18给系统打压力,内存占用上去了,停止打压后,仍然降不下来,就可能是有泄漏。对于无状态的服务,连接上有请求过来,内存上去了。停了请求,但是内存仍然居高不下,等到连接断开内存才降,则sessi...

  • 7

    在某次巡查生产环境监控数据的时候,发现某个程序的内存占用偏高(大于500M)。对于这个程序的作用需要简单交代一下,这个程序是用做通讯服务程序,通过Socket与IOT设备进行通讯。因为了解这个程序的使用场景,所以对于该程序的内存占用偏高产生了怀疑。该程序...

  • 13
    • itimetraveler.github.io 3 years ago
    • Cache

    【android】内存泄漏分析心得 | iTimeTraveler

    本文来源:

  • 6

    1. 讲故事 前天那位 his 老哥又来找我了,上次因为

  • 4

    1. 讲故事 上周四有位朋友加wx咨询他的程序内存存在一定程度的泄漏,并且无法被GC回收,最终机器内存耗尽,很尴尬。 沟通下来,这位朋友能力还是很不错的,也已经做了初步的dump分析,发现了托管堆上有 10w+ 的 byte[] 数组,并占...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK