垃圾回收

垃圾回收机制

可以作为Gc Root引用的点的是

  1. JavaStack中引用的对象
  2. 方法区中静态引用指向的对象
  3. 方法区中常量引用指向的对象
  4. Native方法中JNI引用的对象

确定是否存在内存泄漏

查看Android Profile ,点击Dump Java Heap,然后我们就可以在下面的区域看到每个对象所占有的内存情况

内存泄漏总结_内存泄漏

如果想对结果进行过滤,可以点击右侧的Filter,例如我们想查看我们应用的内存情况,可以输入包名

内存泄漏总结_java_02

下面是某个具体类所占用的内存情况,其中Allocations代表内存中总共为多少个对象分配了内存,

内存泄漏总结_数组_03

下面我们做一个内存泄漏的测试,代码如下

public class TimeActivity extends AppCompatActivity {
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Toast.makeText(TimeActivity.this, "收到", Toast.LENGTH_SHORT).show();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_time);
}

public void send(View view){
handler.sendEmptyMessageDelayed(0,10000);
}
}

每次打开页面,我们发送一个延迟消息,然后重复几次,这时候进行内存分析,可以看到如下的结果

内存泄漏总结_java_04

内存中出现了三个Activity的实例,说明发生了内存泄漏,我们也可以用命令行来查看当前内存的情况

adb shell dumpsys meminfo 包名 -d

结果如下

Applications Memory Usage (in Kilobytes):
Uptime: 15584464 Realtime: 32865994

** MEMINFO in pid 10619 [practice.lxn.cn.androidpractice] **
Pss Private Private SwapPss Heap Heap Heap
Total Dirty Clean Dirty Size Alloc Free
------ ------ ------ ------ ------ ------ ------
Native Heap 6478 6428 0 0 12800 8998 3801
Dalvik Heap 2778 2696 0 0 10481 6385 4096
Dalvik Other 620 616 0 0
Stack 220 220 0 0
Ashmem 55 4 0 0
Other dev 5 0 4 0
.so mmap 1560 160 272 37
.apk mmap 183 0 48 0
.ttf mmap 23 0 8 0
.dex mmap 2048 4 2044 0
.oat mmap 2002 0 308 0
.art mmap 1755 884 220 11
Other mmap 14 4 0 0
EGL mtrack 103 103 0 0
GL mtrack 4048 4048 0 0
Unknown 510 508 0 1
TOTAL 22451 15675 2904 49 23281 15383 7897

App Summary
Pss(KB)
------
Java Heap: 3800
Native Heap: 6428
Code: 2844
Stack: 220
Graphics: 4151
Private Other: 1136
System: 3872

TOTAL: 22451 TOTAL SWAP PSS: 49

Objects
Views: 68 ViewRootImpl: 1
AppContexts: 6 Activities: 4
Assets: 4 AssetManagers: 2
Local Binders: 15 Proxy Binders: 21
Parcel memory: 3 Parcel count: 15
Death Recipients: 1 OpenSSL Sockets: 0

Dalvik
isLargeHeap: false

SQL
MEMORY_USED: 0
PAGECACHE_OVERFLOW: 0 MALLOC_SIZE: 0

下面说一下Shallow Size和Retain Size的区别:

Shallow Size是对象本身占据的内存的大小,不包含其引用的对象。对于常规对象(非数组)的Shallow Size由其成员变量的数量和类型来定,而数组的ShallowSize由数组类型和数组长度来决定,它为数组元素大小的总和。
Retained Size=当前对象大小+当前对象可直接或间接引用到的对象的大小总和。(间接引用的含义:A->B->C,C就是间接引用) ,并且排除被GC Roots直接或者间接引用的对象