内存相关

来源:互联网 发布:双色球杀号软件 编辑:程序博客网 时间:2024/05/30 07:12

一,理论概念:
1,RAM(random access memory):运存,物理位置是位于手机内部的随机存储器上,断电后资料丢失,相当于windows电脑内存条。
最早的内存大小才80M,而现在一般内存大小已经达到1G,近年来2G内存已经成为主流,也有一些手机是3.5G与4G、8G等大小。一般来说内存越大,运行起来更流程。
每个APP运行起来后说到的Dalvik Size和Native Size就是占用的这里的存储空间。

2,ROM(Read-Only Memory): 理解为机身存储,不要简单的理解成只读内存,物理位置是位于手机内部的非易失性存储器上,断电后依然能够保存资料,相当于windows硬盘。
所谓的“刷ROM”(或是刷包)就是将官方或是第三方的ROM镜像文件通过工具烧写到ROM中的过程,通过这种“刷ROM”,把硬件概念的存储器在软件层面进行了划分。
主要包括:1,内部存储器:
系统存储(/system) ContentProvider
系统缓存(/cache)
内部存储(/data) Shared Preferences和SQLite
2,外部存储器: 外部存储(/mnt/sdcard)

内部存储器与外部存储器的区别:
所有的安卓设备都有外部存储和内部存储,这两个名称来源于安卓的早期设备,那个时候的设备内部存储确实是固定的,而外部存储确实是可以像U盘一样移动的。但是在后来的设备中,很多中高端机器都将自己的机身存储扩展到了8G以上,他们将存储在概念上分成了”内部internal” 和”外部external” 两部分,但其实都在手机内部。所以不管安卓手机是否有可移动的sdcard,他们总是有外部存储和内部存储。最关键的是,我们都是通过相同的api来访问可移动的sdcard或者手机自带的存储(外部存储)。
外部存储虽然概念上有点复杂,但也很好区分,你把手机连接电脑,能被电脑识别的部分就一定是外部存储。

/*android 获取系统默认路径:/
Environment.getDataDirectory().getPath() : /data
Environment.getDownloadCacheDirectory().getPath() : /cache
Environment.getExternalStorageDirectory().getPath(): /mnt/sdcard(与/sdcard是一样的内容)
Environment.getRootDirectory().getPath() :/system
Context.getCacheDir().getPath() : /data/data/com.zhd/cache
Context.getExternalCacheDir().getPath() :/mnt/sdcard/Android/data/com.zhd/cache
Context.getFilesDir().getPath() :/data/data/com.zhd/files
Context.getObbDir().getPath() :/mnt/sdcard/Android/obb/com.zhd
Context.getPackageName() : com.zhd
Context.getPackageCodePath() :/data/app/com.zhd-1.apk
Context.getPackageResourcePath() :/data/app/com.zhd-1.apk
注:不同的设备上,调用getExternalStorageDirectory()返回值会不一样,这个方法返回的是当前设备厂商所认为的“外部存储”,通过扫描系统文件遍历”system/etc/vold.fstab”确定。
1.一部分手机将eMMC存储挂载到 /mnt/external_sd 、/mnt/sdcard2 等节点,而将外置的SD卡挂载到Environment.getExternalStorageDirectory()这个结点。
此时,调用Environment.getExternalStorageDirectory(),则返回外置的SD的路径/scard1。
2.而另一部分手机直接将eMMC存储挂载在Environment.getExternalStorageDirectory()这个节点,而将真正的外置SD卡挂载到/mnt/external_sd、/mnt/sdcard2 等节点。

参考:
http://blog.csdn.net/u011026329/article/details/47956555
http://blog.csdn.net/hzhdy/article/details/50726133

二,内存查看:
1,查看dalvik的vm heapsize:
命令:
adb shell getprop | grep dalvik.vm.heapgrowthlimit
结果:
注:Android系统对dalvik的vm heapsize作了硬性限制,当java进程申请的java空间超过阈值时,就会抛出OOM异常(这个阈值可以是48M、24M、16M等,视机型而定)

2,查看当前RAM使用情况:
命令:
adb shell cat /proc/meminfo
结果:
MemTotal: 3799860 kB 所有可用RAM大小
MemFree: 179972 kB LowFree与HighFree的总和,被系统留着未使用的内存。
MemAvailable: 1398364 kB
Buffers: 83796 kB
Cached: 1371456 kB
SwapCached: 11632 kB
Active: 1351656 kB
….

Dalvik内存多了会OOM
Native Heap多了会触发memory killer会杀进程释放RAM

3,查看单个进程(Heap Size):
命令:
adb shell dumpsys meminfo com.android.phone
结果:
* MEMINFO in pid 2417 [com.android.phone] *
Pss Private Private SwapPss Heap Heap Heap
Total Dirty Clean Dirty Size Alloc Free
—— —— —— —— —— —— ——
Native Heap 6720 6664 16 0 38912 25157 13754
Dalvik Heap 8484 8456 12 0 9504 3360 6144
Dalvik Other 3476 3476 0 308
Stack 40 40 0 20
Ashmem 0 0 0 0
Other dev 12 4 8 0
.so mmap 1961 88 844 561
.jar mmap 0 0 0 32
.apk mmap 2010 0 1732 8
.ttf mmap 87 0 8 0
.dex mmap 10049 0 8408 32
.oat mmap 5811 0 3772 0
.art mmap 6894 6432 80 1667
Other mmap 25 0 0 4
Unknown 1301 1300 0 1151
TOTAL 50653 26460 14880 3783 48416 28517 19898

4,查看系统各个进程(PSS):
命令:
adb shell procrank
结果:
PID Vss Rss Pss Uss Swap PSwap USwap ZSwap cmdline
2193 2718532K 227964K 174412K 166928K 107508K 93726K 93340K 27488K com.android.systemui
1830 2648720K 208164K 145148K 131752K 28916K 15200K 14816K 4458K system_server
3078 2240216K 179580K 130557K 121144K 113772K 102279K 101440K 29996K com.htc.launcher
2417 2433636K 92376K 42019K 36216K 25372K 11637K 11248K 3412K com.android.phone
4352 2404088K 87952K 41679K 34520K 29576K 15560K 15156K 4563K com.android.settings
注:
VSS - Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)
RSS - Resident Set Size 实际使用物理内存(包含共享库占用的内存)
PSS - Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)
USS - Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)

参考:
http://blog.csdn.net/bigconvience/article/details/35553983

三,内存问题
1,OOM,面向单个进程,即OutOfMemory,堆内存溢出,也就是该app的Dalvik占用内存超过了前面说的vm heapsize。
原因:
(1)数据库的cursor没有关闭。
(2)构造adapter没有使用缓存contentview。
(3)调用registerReceiver()后未调用unregisterReceiver()
(4)未关闭InputStream/OutputStream。
(5)Bitmap使用后未调用recycle()。
(6)Context泄漏。
(7)static关键字等
分析方法:
可使用MAT工具
http://blog.csdn.net/caroline_wendy/article/details/50619746
http://blog.csdn.net/chenbifeng/article/details/51582268

2,LowMemoryKiller,面向系统,当RAM中的MemFree不足时触发LowMemoryKiller杀死oom adj优先级低的进程,回收内存。
原因:
(1)APP原因,同时运行多个APP或太多进程。
(2)手机硬件局限。
分析方式:
adb shell cat /proc/meminfo
结合相关log分析