内存占用大小有如下规律 VSS >= RSS >= PSS >= USS
VSS - Virtual Set Size (用处不大)虚拟耗用内存(包含共享库占用的内存)
RSS - Resident Set Size (用处不大) 实际使用物理内存(包含共享库占用的内存)
PSS - Proportional Set Size (仅供参考)实际使用的物理内存(比例分配共享库占用的内存)
USS - Unique Set Size (非常有用)进程独自占用的物理内存(不包含共享库占用的内存)
top | grep app名称
ps | grep app名称
procrank | grep app名称
dumpsys meminfo app名称
前两个命令只能查到VSS RSS内存占用信息
而后面两个命令可以查出 PSS USS内存占用.
dumpsys meminfo 可以查出native和dalvik分别占用多少内存
dumpsys 用来给出手机中所有应用程序的信息,并且也会给出现在手机的状态。
dumpsys [Option]
meminfo 显示内存信息
cpuinfo 显示CPU信息
account 显示accounts信息
activity 显示所有的activities的信息
window 显示键盘,窗口和它们的关系
wifi 显示wifi信息
首先了解两个概念:
-
私有内存(Dirty and Clean): 进程独占内存。也就是进程销毁时可以回收的内存容量。通常private Dirty内存是最重要的部分,因为只被自己进程使用。Dirty内存是已经被修改的内存页,因此必须常驻内存(因为没有swap);Clean内存是已经映射持久文件使用的内存页(例如正在被执行的代码),因此一段时间不使用的话就可以置换出去。
-
实际使用内存(PSS): 将跨进程共享页也加入进来, 进行按比例计算PSS。这样能够比较准确的表示进程占用的实际物理内存。
通常我们需要关注PSS TOTAL 和 Private Dirty .
Dalvik Heap
dalvik虚拟机分配的内存。PSS Total包含所有Zygote分配使用的内存,共享跨进程加权。PrivateDirty 是应用独占内存大小,包含独自分配的部分和应用进程从Zygote复制时被修改的Zygote分配的内存页。 HeapAlloc 是Dalvik堆和本地堆分配使用的大小,它的值比Pss Total和Private Dirty大,因为进程是从Zygote中复制分裂出来的,包含了进程共享的分配部分。.so mmap & .dex mmap ... mmap
映射本地或虚拟机代码到使用的内存中。Unknown
无法归类的其他项。主要包括大部分的本地分配。Native Heap native
代码申请的内存, 堆和栈,及静态代码块等。TOTAL
进程总使用的实际内存。Objects
中显示持有对象的个数。这些数据也是分析内存泄漏的重要数据。如activity等。
多线程的应用在Android
开发中是非常常见的,常用方法主要有:
- 继承Thread类
- 实现Runnable接口
- Handler
- AsyncTask
- HandlerThread
内部原理 = Thread类 + Handler类机制,即:
通过继承Thread类,快速地创建1个带有Looper对象的新工作线程 通过封装Handler类,快速创建Handler & 与其他线程进行通信 5. 使用步骤 HandlerThread的本质:继承Thread类 & 封装Handler类 HandlerThread的使用步骤分为5步 // 步骤1:创建HandlerThread实例对象 // 传入参数 = 线程名字,作用 = 标记该线程 HandlerThread mHandlerThread = new HandlerThread("handlerThread");
// 步骤2:启动线程 mHandlerThread.start();
// 步骤3:创建工作线程Handler & 复写handleMessage() // 作用:关联HandlerThread的Looper对象、实现消息处理操作 & 与其他线程进行通信 // 注:消息处理操作(HandlerMessage())的执行线程 = mHandlerThread所创建的工作线程中执行 Handler workHandler = new Handler( handlerThread.getLooper() ) { @Override public boolean handleMessage(Message msg) { ...//消息处理 return true; } });
// 步骤4:使用工作线程Handler向工作线程的消息队列发送消息 // 在工作线程中,当消息循环时取出对应消息 & 在工作线程执行相关操作 // a. 定义要发送的消息 Message msg = Message.obtain(); msg.what = 2; //消息的标识 msg.obj = "B"; // 消息的存放 // b. 通过Handler发送消息到其绑定的消息队列 workHandler.sendMessage(msg);
// 步骤5:结束线程,即停止线程的消息循环 mHandlerThread.quit();