如果你参加面试,面试官经常会问到你的一个问题可能是:你在开发过程中,有过排除内存泄漏的经验吗?对于一个合格的Android/C/java开 发老手,这个问题想必已经深入你的心;若是一名新手或者一直对内存泄漏这个东西模模糊糊的工程师,你的答案可能让面试官并不满意,这里将从底到上对内存泄 漏的原因、排查方法和一些经验为你做一次完整的解剖。' i s' z) N! U# K8 |) x9 X
+ |+ V7 I, W5 E' o1 F处理内存泄漏的问题是将软件做到极致的一个必须的步骤,尤其是那种将被用户高强度使用的软件。 " w3 x+ K' {4 _##一个简单的C和Android的例子% Y( s/ H7 T5 E
一个最简单的C的内存泄漏的例子: , R# K# {; P. M% g1 W6 P$ [``` 3 G& @3 c9 P3 j, [( T# `$ hchar *ptr1 = (char *)malloc(10);! H4 ]4 a/ N$ w! U' k, u
char *ptr2 = (char *)malloc(10);5 \% o' A1 r5 H, p/ _0 x
ptr2 = ptr1;3 [: A/ z) N& g1 l: P1 J
free(ptr1), g4 D5 m1 ^: q( E( ` R
```) O# C% ], d) t6 x% _ M; k- r
这里最后发生了10个字节的内存泄漏,那么到底发生了什么?+ r$ r# f5 A6 @
" T. @( q! _6 A1 U& Z6 e
首先各自分配了两块10个字节的内存,分别用叫ptr1和ptr2的指针指向这两块内存(就像是java中的引用),然后呢让ptr2也指向一开始 ptr1指向的那块内存(这时候ptr1和ptr2都指向了ptr1一开始指向的那个10个字节的内存),最后用free将ptr1指向的那块内存给释放 了——>结果就是一开始ptr2指向的那块内存发生了泄漏(没人用了却又回收不掉)6 T2 r* i- d1 i9 G3 r
, w0 M+ T3 H! |* a; z! K0 T5 U: r
可能你会说Java有内存垃圾回收机制,不要考虑谁分配和释放的访问,那么下面这个例子就会让你明白你错了:' S+ c# m" Y% t
```3 E! f3 V7 P* d
public class PendingOrderManager { / q) c) {1 Y- _8 d6 J# j7 B private static PendingOrderManager instance;0 F1 o6 M4 c/ Y
private Context mContext;" ?: F" |- f, u
public PendingOrderManager(Context context) { 0 l8 z" p5 X! U" H9 } + c- B3 K( a; K( k5 @
this.mContext = context;9 Y$ I9 Q6 y7 V8 O
} 6 g" w# h" m" s: R: I! c" \/ D1 e * n3 [- w5 @+ i+ T7 J9 }/ M3 m3 m public static PendingOrderManager getInstance(Context context) {0 f5 s) A; p7 O9 ~# {, ?* n6 I a$ }
if (instance == null) {: e) g) R* T& U6 C
instance = new PendingOrderManager(context); 8 H7 R! I3 W( c2 L } 0 h. J* l( |2 V6 r0 I V return instance; % ^# c4 Y" o" e3 _3 M% F( B7 x }0 h- q# d8 u$ |2 K, M- v
, d& S7 b- i1 X
public void func(){ ) x3 ~4 d/ m' D( k S& L& u8 H ... c. i4 \9 y8 ^: x) s9 e e } u: a& x* n; v( ^4 Z: @2 a...9 k8 g5 u- b2 m& @# a# n1 i
} . g! Y' R1 w% I- K, v% w7 ?, R``` ) Q* b z& M! ~1 }9 n- P8 V4 ?+ M) j( @8 a7 x* G8 c8 R3 `7 ~6 U$ d
然后让你的某个Activity去使用这个PendingOrderManager单例,并且某个时候退出这个Activity: - T- E2 w' s& E5 S4 L' |7 M- k``` + @" V1 [0 w5 w% ?3 e//belong to some Activity! o! a: ^% \) N3 {% L- j6 ^: z
PendingOrderManager.getInstance(this).func(); 4 Q1 u' u; s' S& _7 p... & A W* M8 ?. C4 D( _finish(), a! W' H& `4 Q B. `, n' [' d6 ^& l- X
```2 M; {& x" O$ w/ x
这个时候内存泄漏已经发生:你退出了你的这个Activity本以为java的垃圾回收会将它释放,但实际上Activity一直被 PendingOrderManager持有着。Acitivity这个Context被长生命周期个体(单例一旦被创建就是整个app的生命周期)持有 导致了这个Context发生了内存泄漏。# {6 z* B- d4 S5 k/ \