1.Android内存的管理方式
Android系统内存分配和回收方式
一个app通常就是一个进程对应一个虚拟机,使用adb shell --> ps可以查看所有进程信息,具体内存相关信息可以使
用dumpsys meminfo packagename查看,如下:
generic_x86:/ $ dumpsys meminfo xxx
Applications Memory Usage (in Kilobytes):
Uptime: 334565 Realtime: 334565
** MEMINFO in pid 2898 [xxx] **
Pss Private Private SwapPss Heap Heap Heap
Total Dirty Clean Dirty Size Alloc Free
------ ------ ------ ------ ------ ------ ------
Native Heap 8173 8124 0 0 25088 22685 2402
Dalvik Heap 10553 10444 0 0 11928 7832 4096
Dalvik Other 1329 1328 0 0
Stack 424 424 0 0
Ashmem 4 4 0 0
Other dev 4 0 4 0
.so mmap 1783 128 360 0
.apk mmap 282 0 12 0
.ttf mmap 79 0 44 0
.dex mmap 10976 180 10796 0
.oat mmap 2523 0 592 0
.art mmap 1795 1476 0 0
Other mmap 2191 4 1956 0
Unknown 806 800 0 0
TOTAL 40922 22912 13764 0 37016 30517 6498
App Summary
Pss(KB)
------
Java Heap: 11920
Native Heap: 8124
Code: 12112
Stack: 424
Graphics: 0
Private Other: 4096
System: 4246
TOTAL: 40922 TOTAL SWAP PSS: 0
Objects
Views: 325 ViewRootImpl: 1
AppContexts: 2 Activities: 1
Assets: 2 AssetManagers: 2
Local Binders: 9 Proxy Binders: 15
Parcel memory: 4 Parcel count: 18
Death Recipients: 0 OpenSSL Sockets: 2
WebViews: 0
SQL
MEMORY_USED: 0
PAGECACHE_OVERFLOW: 0 MALLOC_SIZE: 0
并且GC在HEAP剩余空间不够时才发出垃圾回收动作;GC触发时,所有其他线程是被暂停的。
APP内存限制机制
每个app分配都有最大内存限制,随着不同设备而不同。android系统是多任务系统,允许多应用同时运行,我们
不能让一个app吃掉设备所有内存,其他app没有内存占用而无法同时运行;如下:
public static void calculate(Context context){
StringBuilder sb = new StringBuilder();
ActivityManager atm = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
//app运行手机对app的内存最大限制。
int memClass = atm.getMemoryClass();
//原则上LargememClass是在androidmanifest里设置了 largeheap=true后,能获得更大的上限,不过大部分手机这个值和memClass是一样的。
//小米4手机 memClass:128 largememClass:512
int largememClass = atm.getLargeMemoryClass();
sb.append("memClass:" + memClass +"\n");
sb.append("largememClass:" + largememClass +"\n");
//freeMemory(),totalMemory(),maxMemory()反映的都是java这个进程的内存情况,跟操作系统的内存根本没有关系。
//totalMemory()java虚拟机这个进程当时所占用的内存,从操作系统那里挖过来用上的内存
Float totalMemory = Runtime.getRuntime().totalMemory() * 1.0f / (1024*1024);
//freeMemory() java虚拟机100%的情况下是会稍微多挖一点的,这些挖过来而又没有用上的内存
Float freeMemory = Runtime.getRuntime().freeMemory() * 1.0f / (1024*1024);
//maxMemory()java虚拟机(这个进程)能构从操作系统那里挖到的最大的内存,小米4手机maxMemory:128.0
Float maxMemory = Runtime.getRuntime().maxMemory() * 1.0f / (1024*1024);
sb.append("totalMemory:" + totalMemory +"\n");
sb.append("freeMemory:" + freeMemory +"\n");
sb.append("maxMemory:" + maxMemory +"\n");
Log.e("MemoryUtils.calculate",sb.toString());
}
切换应用时后台App清理机制
app清理回收算法是LRU,当系统清理app的时候,会调用onTrimMemery。
监控内存的几种方式
1.device monitor里内存走势图查看memory整体占用情况;
2.通过device monitor 操作heap-->Cause GC可以看到一些信息,如下图:
3.hprof文件对比查看内存泄漏,查看的是某一时刻Java堆中对象的变化。主要比较某一对象,在2个文件中的数量大
小,内存占用大小变化
4.traceview进行内存泄漏的查看,查看的是内存中的函数调用变化。一类是调用次数不多,但每次调用却需要花费
很长时间的函数。一类是那些自身占用时间不长,但调用却非常频繁的函数。
2.App内存优化方法
数据结构优化
频繁字符串拼接使用stringbuilder,它比+拼接高效;大数据量存储使用ArrayMap,SparseArray替代HaspMap;避
免内存抖动,避免大量分配了一些局部变量。
对象复用
复用系统自带的资源,例如adapter中的ContentView;避免在onDraw里创建对象;对象池设计的应用。
避免内存泄漏
内存泄漏导致剩余可用heap堆越来越少,频繁出发GC。
内存泄漏的例子:查询数据库而没有关闭Cursor;调用registerReceiver后未调用unregisterReceiver();未关闭
InputStream/OutputStream;Bitmap使用后未调用recycle();Context泄露,Activity在销毁后,由于被静态变量引用,
内存不会被释放,或者被未运行完的线程引用也不会释放。
3.避免oom
避免方法
即使回收bitmap;
避免bitmap浪费空间;
try catch提示用户内存使用太大;
对bitmap进行处理;
做bitmap cache管理时,软引用bitmap,可以在系统内存不够时会释放软引用的对象。
处理bitmap方法
例如一个jpg图片文件大小~11M,实际加载到bitmap~22M。
尺寸:按比例取样图片BitmapFactory.Options.inSampleSize;如下:
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// 第一次解析将inJustDecodeBounds设置为true,来获取图片大小
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// 调用上面定义的方法计算inSampleSize值
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// 使用获取到的inSampleSize值再次解析图片
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
RGB色彩储存模式:
public static final Bitmap.Config ALPHA_8
public static final Bitmap.Config ARGB_4444
public static final Bitmap.Config ARGB_8888
public static final Bitmap.Config RGB_565
参考文档
慕课网上app内存优化的相关视频。http://blog.csdn.net/wgw335363240/article/details/8878644
http://www.cnblogs.com/sunzn/p/3192231.html