android sdk tools_android sdk tools_android sdk tools

/ 今日科技快讯 /

昨日,美国商务部产业安全局在其官网上宣布,将28家中国组织和企业列入“实体清单”,其中包括海康威视、科大讯飞、旷世科技、大华科技、厦门美亚柏科信息有限公司、依图科技、颐信科技有限公司共8家人工智能公司。

/ 作者简介 /

本篇文章来自的投稿,分享了开发内存优化的相关知识,希望对大家有所帮助!同时也感谢作者贡献的精彩文章。

的博客地址:

/ 内存的划分 /

分类的标准

JMM

划分区域

VSS/RSS/PSS/USS

///..

java///stack/code/othe

方法区/java堆/java栈/栈/程序计数器

是一个adb的root指令,可以查询内存的划分:

android sdk tools_android sdk tools_android sdk tools

那么最值得关注的是PSS和USS,我们可以用 来查询(无需root权限)

查询pss划分

android sdk tools_android sdk tools_android sdk tools

重点字段解读:

通过上面图片可得 app占用的内存是250M,大部分内存在 Heap、code、,那如何分析和解决,我们下面讲。

是ide提供出来的分类:

JMM 分类

注意:

/ Java内存优化 /

Java内存优化

内存泄漏

内存抖动

大内存对象使用

发生的场景

单例、匿名内部类、接口忘记释放 ...

拼接、循环内重复生成对象 ...

、 ...

Java检查泄漏 - 使用

结果分析

可以检查 View界面的泄漏问题。通过接入跑上接着静等java内存泄漏的出现:

android sdk tools_android sdk tools_android sdk tools

通过上图可以知道被.持有,是一个单例,然后最顶层的.就是GC root(注意:静态变量不是GC root),.是类,只要把 的换成那就解决了。

中GC root有哪些:

的核心原理:

小结

那么只能解决界面上的泄漏,其他内存上的优化是做不到的,譬如:线程池的泄漏,内存的抖动,大对象的滥用.. 那么就需要更为强大的工具MAT了。

内存检测工具MAT

MAT是分析内存文件hprof的工具。

抓取步骤

跑几分钟后,退回应用主界面,手动多次点击GC按钮,把可回收的回收掉,为了剔除脏数据。通过 的把内存文件hprof给dump下来。

分析内存

完成以上步骤之后的结果图。

android sdk tools_android sdk tools_android sdk tools

android sdk tools_android sdk tools_android sdk tools

android sdk tools_android sdk tools_android sdk tools

android sdk tools_android sdk tools_android sdk tools

为了避免查看太多并不是强相关的对象,直接从本应用的java 类入手,MAT 也提供正则式过滤,直接输入.com.vd.(本应用 )去过滤,结果就非常明显,整个应用自己写的对象占用的内存都在这里。从大的对象下手,是否这个对象有存在的意义,是否需要占这么大的一个内存。是否可以对其做相应的处理。

android sdk tools_android sdk tools_android sdk tools

MAT提供了更加方便的OQL查询,可以找到指定一个名字的对象,包括可以根据本身java对象的成员属性来做条件语句。譬如上图我找长宽都大于100px的图片都有哪些。可以把大图片揪出来。

小结

可先用跑出明显的内存泄漏,再用MAT检查整个应用的内存分布状况,去优化该优化的Java堆内存。

/ 内存优化 /

内存优化

DDMS

root权限

需要

需要

不需要

环境

jni

需要使用sdk18 的 tools/ddms.bat(sdk 18之后就被剔除了)

步骤

开启 debug模式,打开cmd窗口输入。

//查询所有内存
adb shell setprop wrap.packagename '"LIBC_DEBUG_MALLOC_OPTIONS=backtrace logwrapper"'

//查询内存泄漏
adb shell setprop wrap.packagename '"LIBC_DEBUG_MALLOC_OPTIONS=leak_track logwrapper"'

android sdk tools_android sdk tools_android sdk tools

android sdk tools_android sdk tools_android sdk tools

通过adb shell am -n

/data/local/tmp/heap.txt把文件抓取出来到/data/local/tmp/heap.txt。

android sdk tools_android sdk tools_android sdk tools

把内存文件拷贝出来,等下分析。

使用分析

搭建环境

android sdk tools_android sdk tools_android sdk tools

修改代码

修改er.py 代码中NDK配置地方:

resByte = subprocess.check_output(["G:/AndroidNDK/android-ndk-r17/toolchains/aarch64-linux-android-4.9/prebuilt/windows-x86_64/bin/aarch64-linux-android-objdump""-w""-j"".text""-h", sofile])

p = subprocess.Popen(["G:/AndroidNDK/android-ndk-r17/toolchains/aarch64-linux-android-4.9/prebuilt/windows-x86_64/bin/aarch64-linux-android-addr2line""-C""-j"".text""-e", sofile, "-f"], stdout=subprocess.PIPE, stdin=subprocess.PIPE)

替换def (self):函数中的部分代码android sdk tools,把下面代码:

if len(extra_args) !1:
      print(self._usage)
      sys.exit(1)

替换为:

self.symboldir = "C:/Users/chaojiong.zhang/Documents/AndroidStudio/DeviceExplorer/xiaomi-mi_8-4b429b4"
extra_args.append("dump.txt")

self. - 就是dump.txt 里面的内存地址都需要 通过so库来查找对应的是哪一个函数。而so存放的父路径地址就是self.,那么也就是说需要把 手机上的//lib64、//lib64/整个 文件夹pull 下来到电脑上,譬如这里是pull到C:/Users/.zhang////-mi_8-。

android sdk tools_android sdk tools_android sdk tools

在def main():函数插入部分代码在函数第一行插入和最后一行插入以下代码,目的是直接把结果log输出到test.txt可以直接查看。

def main():
sys.stdout 
= open("test.txt""w")


 //...
sys.stdout.close()

跑起来看看。

内存文件分析

字段解读

内存信息分析一

10285756  58.29%  99.95%       49     eac0b276 /system/lib/libhwui.so android::Bitmap::allocateHeapBitmap(SkBitmap*)

可以看得出来 方法占用了,10M左右的内存,占总内存 58.29%,占父帧 99.95%(意思是:A-> B ,A方法调用B方法,A方法总共占用了10M,其中9.9M是在B方法中申请的,那么% 就是99%),调用了49次,动作发生在.so中的 ::::方法。下面是被调用的流程:

BitmapFactory.decodeResource -> BitmapFactory.nativeDecodeStream ->BitmapFactory.cpp 中 nativeDecodeStream() -> doDecode() -> SkBitmap.tryAllocPixels() -> ... -> android::Bitmap::allocateHeapBitmap()

Bitmap.createBitmap -> nativeCreate() -> Bitmap.cpp 中的 nativeCreate() -> GraphicsJNI.cpp zhong de allocateJavaPixelRef() -> ... -> android::Bitmap::allocateHeapBitmap()

也就是说java层的 创建都会跑到这个函数。那么上面这个占用了10M的 ,究竟是java层哪个类调用下来的,这个目前是无解(包括最近华为的方舟环境平台也不行),只能在java层去全盘查询了,哪些图片使用了较多的内存。

内存信息分析二

小结

内存目前无法很清晰的定位到对应的java层代码,无解。只能看个大概,然后有目的性去排查某个类,或者某个模块。

/ 内存优化 /

若应用没有自己接入/ GL / GL 开源库,来绘制图形,可不必理会。毕竟已经超出应用工程师的范围了。

/ stack内存优化 /

解决栈溢出

死循环问题

JDK 1.8之前的,避免使用多线程造成死循环问题。

递归问题

避免深层次的递归问题,较深层次的递归可采用尾递归的方法。递归的退出,最好用标识位退出。或者通过线程(),()去退出递归,确保递归正确退出。递归中如果有.sleep ,要注意中断被消费问题。

问题

对于传递大对象,或者,的上限是505K 。解决方案:

解决重复生成局部变量

避免在循环内重复生成局部变量

 private void memoryShake() {
        ArrayList shakes = new ArrayList();
        for (int i = 0; i < 100; i++) {
            Integer shake = new Integer(i);
            shakes.add(shake);
        }
    }

    private void memoryShake1() {
        ArrayList shakes = new ArrayList();
        Integer shake;
        for (int i = 0; i < 100; i++) {
            shake = new Integer(i);
            shakes.add(shake);
        }
    }

()会在循环内生成100个shake局部变量+100个局部变量的引用,()会在循环内生成100个shake局部变量+1个局部变量的引用,一个对象引用在64bit的环境是8byte 。100*8 = 800 byte = 0.8KB。

使用问题

循环内字符的拼接不要使用+符号,(使用+符号android sdk tools,编译成字节码后,循环内会生成对象去拼接)。正确应该使用(线程安全)或者(线程不安全)。

/ code内存优化 /

code内存消耗主要是:so库,dex,ttf。

以上三种文件都是要加载到运行内存才能被解析运行,所以它们的体积要算进自身的应用内存中。

so库,可以通过STRIP去掉一些符号表和调试信息,在.mk加入 := true,即可。

dex,是java代码编译成的字节码,没混淆的apk中的dex会大很多,混淆后的dex 会小很多,所以debug包的内存占用会大于包。 3.3带了了一个新特性R8压缩,可以在.加入 .=true ,减小dex包的体积(完美兼容现有混淆)。当然还要剔除自身应用的无用代码,可使用 Menu > > 进行排查,这里不再详细展开。

ttf - 如果应用中只用到部分字体,可通过提取使用的字体。


限时特惠:
本站持续每日更新海量各大内部创业课程,一年会员仅需要98元,全站资源免费下载
点击查看详情

站长微信:Jiucxh

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注