线程计数器中如果正在执行java方法,计数器记录的是当前指令的地址,
如果是Native方法,计数器记录为空
堆内存 = 新生代(1) + 老年代(2)
也叫“永久代”,1.8以后将方法区去除了,将方法区移动到直接内存
内存回收主要考虑堆区和方法区的回收,其他部分会根据线程的产生和消亡
堆中的老年代和方法区(永久代)是绑定的,无论哪一方满了,都会触发双方的GC回收
年轻代分为eden、s0、s1区,分别为8:1:1,年轻代和老年代为1:2
Minor GC : 清理年轻代
Major GC : 清理老年代
Full GC : 清理整个堆空间,包括年轻代和永久代
在内存泄露问题处理上,使用最多的是弱引用,许多源码、框架都是用
eg:
- ThreadLocalMap中存储以ThreadLocal的弱引用为键,具体内容为value
- Glide中缓存使用activeResource,存储的是图片的弱引用
- 解决Handler的内存泄漏使用弱引用
所有的引用都是继承自Reference,以下以WeakReference为例:
public class WeakReference<T> extends Reference<T> {
/**
* Creates a new weak reference that refers to the given object. The new
* reference is not registered with any queue.
*
* @param referent object the new weak reference will refer to
*/
public WeakReference(T referent) {
super(referent);
}
/**
* Creates a new weak reference that refers to the given object and is
* registered with the given queue.
*
* @param referent object the new weak reference will refer to
* @param q the queue with which the reference is to be registered,
* or null if registration is not required
*/
public WeakReference(T referent, ReferenceQueue<? super T> q) {
super(referent, q);
}
}
其中存在两种构造方法,区别在于是否传入引用队列,如果不传入引用队列,说明只存在一种引用,不需要引用队列成链存储
public abstract class Reference<T> {
private static boolean disableIntrinsic = false;
private static boolean slowPathEnabled = false;
//引用的对象,由垃圾回收器控制其引用
volatile T referent; /* Treated specially by GC */
final ReferenceQueue<? super T> queue;
Reference queueNext;
Reference<?> pendingNext;
public T get() {
return getReferent();
}
@FastNative
private final native T getReferent();
public void clear() {
clearReferent();
}
@FastNative
native void clearReferent();
public boolean isEnqueued() {
// Contrary to what the documentation says, this method returns false
// after this reference object has been removed from its queue
// (b/26647823). ReferenceQueue.isEnqueued preserves this historically
// incorrect behavior.
return queue != null && queue.isEnqueued(this);
}
public boolean enqueue() {
return queue != null && queue.enqueue(this);
}
/* -- Constructors -- */
Reference(T referent) {
this(referent, null);
}
Reference(T referent, ReferenceQueue<? super T> queue) {
this.referent = referent;
this.queue = queue;
}
}
抽象类很简短,可以看出一个关键点,Reference是一个节点,保存next的引用,方法调用都是使用ReferenceQueue方法,直接进入:
private Reference<? extends T> head = null;
private Reference<? extends T> tail = null;
boolean enqueue(Reference<? extends T> reference) {
synchronized (lock) {
if (enqueueLocked(reference)) {
lock.notifyAll();
return true;
}
return false;
}
}
private boolean enqueueLocked(Reference<? extends T> r) {
...
if (r instanceof Cleaner) {
Cleaner cl = (sun.misc.Cleaner) r;
cl.clean();
r.queueNext = sQueueNextUnenqueued;
return true;
}
if (tail == null) {
head = r;
} else {
tail.queueNext = r;
}
tail = r;
tail.queueNext = r;
return true;
}
入队方法中,
SoftReference
public class SoftReference<T> extends Reference<T> {
//时间戳,由gc更新
static private long clock;
private long timestamp;
public SoftReference(T referent) {
super(referent);
this.timestamp = clock;
}
/**
* Creates a new soft reference that refers to the given object and is
* registered with the given queue.
*
* @param referent object the new soft reference will refer to
* @param q the queue with which the reference is to be registered,
* or null if registration is not required
*
*/
public SoftReference(T referent, ReferenceQueue<? super T> q) {
super(referent, q);
this.timestamp = clock;
}
public T get() {
T o = super.get();
if (o != null && this.timestamp != clock)
this.timestamp = clock;
return o;
}
}
由gc管理时间戳
回收条件为:clock - timestamp <= free_heap * ms_per_mb
PhantomReference
public class PhantomReference<T> extends Reference<T> {
public T get() {
return null;
}
public PhantomReference(T referent, ReferenceQueue<? super T> q) {
super(referent, q);
}
}
虚引用的get方法返回null,不做gc保留
虚引用通过构造方法可以查看是持有对象引用的
总结:所有引用都是继承自Reference基类的,该类是一个链表节点,ReferenceQueue通过这点形成单链表,称之为队列,进行引用管理,所有引用都可以通过Reference的isEnqueue方法判断引用是否存在。
java堆中创建对象时,如果java类定义了finalize方法,就会新建一个FinalizerReference类,指向这个新建的对象
Android studio自带内存、cpu、网络的变化,可以根据内存变化做具体分析
框架集成,自动检测内存泄漏,生成app,提供内存泄漏栈堆情况
原理:绑定生命周期,对Activity和Fragment来说,在onDestory时将对象放入弱引用队列进行存储,触发gc后,如果还存在,则发生内存泄漏
一款比较老的工具,ThreadPolicy可以检测主线程是否网络访问,是否读写。VMPolicy检测内存,Activity,Fragment是否泄漏,资源是否正确关闭
自动装箱就是将基础数据类型转化为对应的复杂类型,在HashMap的增删改查中充满了自动装箱问题,所以尽量避免这中问题,如将HashMap替换为SparseArray和ArrayMap