gc HeapTaskDaemon守护线程
的触发
1. for Alloc : 内存分配的时候
2. Explicit : 显示调用的时候
3. Background : 在后台的时候
Heap类还定义了以下三个垃圾收集接口:
1. CollectGarbage(): 用来执行显式GC,例如用实现System.gc接口。
libcore/luni/src/main/java/java/lang/System.java gc()
libcore/luni/src/main/java/java/lang/Runtime.java public native void gc()
art/runtime/native/java_lang_Runtime.cc Runtime::Current()->GetHeap()->CollectGarbage(false)
art/runtime/gc/heap.cc void Heap::CollectGarbage(bool clear_soft_references)
art/runtime/gc/heap.cc CollectGarbageInternal(collector::GcType gc_type,GcCause gc_cause, boolclear_soft_references)
static void Runtime_gc(JNIEnv*, jclass) { if (Runtime::Current()->IsExplicitGcDisabled()) { LOG(INFO) << "Explicit GC skipped."; return; } Runtime::Current()->GetHeap()->CollectGarbage(false); }
void Heap::CollectGarbage(bool clear_soft_references) { // Even if we waited for a GC we still need to do another GC since weaks allocated during the // last GC will not have necessarily been cleared. CollectGarbageInternal(gc_plan_.back(), kGcCauseExplicit, clear_soft_references); }
2. ConcurrentGC(): 用来执行并行GC,只能被ART运行时内部的GC守护线程执行。
void Heap::ConcurrentGC(Thread* self, bool force_full) { if (!Runtime::Current()->IsShuttingDown(self)) { // Wait for any GCs currently running to finish. if (WaitForGcToComplete(kGcCauseBackground, self) == collector::kGcTypeNone) { // If the we can't run the GC type we wanted to run, find the next appropriate one and try that // instead. E.g. can't do partial, so do full instead. collector::GcType next_gc_type = next_gc_type_; // If forcing full and next gc type is sticky, override with a non-sticky type. if (force_full && next_gc_type == collector::kGcTypeSticky) { next_gc_type = HasZygoteSpace() ? collector::kGcTypePartial : collector::kGcTypeFull; } if (CollectGarbageInternal(next_gc_type, kGcCauseBackground, false) == collector::kGcTypeNone) { for (collector::GcType gc_type : gc_plan_) { // Attempt to run the collector, if we succeed, we are done. if (gc_type > next_gc_type && CollectGarbageInternal(gc_type, kGcCauseBackground, false) != collector::kGcTypeNone) { break; } } } } } }
3. CollectGarbageInternal(): ART运行时内部调用的GC接口,可以执行各种类型的GC。
CollectGarbage()和ConcurrentGC()是被外部调用的接口,CollectGarbageInternal()是内部接口,不能被外部调用。
Heap类的成员变量mark_sweep_collectors_保存了ART运行时内部使用的六种垃圾收集器,这六种垃圾收集器分为两组。其中一组是支持并行GC的,另一组是不支持并行GC的。每一组都由MarkSweep、PartialMarkSweep和StickyMarkSweep三种类型的垃圾收集器组成。
art里面的Closure是一个任务接口,实现run方法,执行特定的功能
class Closure { public: virtual ~Closure() { } virtual void Run(Thread* self) = 0; }; class Task : public Closure { public: // Called after Closure::Run has been called. virtual void Finalize() { } }; class SelfDeletingTask : public Task { public: virtual ~SelfDeletingTask() { } virtual void Finalize() { delete this; } }; class Heap::ConcurrentGCTask : public HeapTask { }; // A closure used by Thread::Dump. class DumpCheckpoint FINAL : public Closure { .......... }
Closure <= Task <= SelfDeletingTask <= HeapTask <= ConcurrentGCTask
Closure <= DumpCheckpoint
1> ConcurrentGC()
// art/runtime/native/dalvik_system_VMRuntime.cc static void VMRuntime_trimHeap(JNIEnv* env, jobject) { Runtime::Current()->GetHeap()->Trim(ThreadForEnv(env)); } static void VMRuntime_concurrentGC(JNIEnv* env, jobject) { Runtime::Current()->GetHeap()->ConcurrentGC(ThreadForEnv(env), true); //直接执行gc } static void VMRuntime_requestHeapTrim(JNIEnv* env, jobject) { // 这里很少看到有调用 Runtime::Current()->GetHeap()->RequestTrim(ThreadForEnv(env)); } // 分配出请求的内存之后,堆剩下的内存超过一定的阀值,就会调用Heap类的成员函数RequestConcurrentGC请求执行一个并行GC。 static void VMRuntime_requestConcurrentGC(JNIEnv* env, jobject) { Runtime::Current()->GetHeap()->RequestConcurrentGC(ThreadForEnv(env), true); //往守护线程添加gc任务 } static void VMRuntime_startHeapTaskProcessor(JNIEnv* env, jobject) { Runtime::Current()->GetHeap()->GetTaskProcessor()->Start(ThreadForEnv(env)); } static void VMRuntime_stopHeapTaskProcessor(JNIEnv* env, jobject) { Runtime::Current()->GetHeap()->GetTaskProcessor()->Stop(ThreadForEnv(env)); //守护线程停止执行任务 } static void VMRuntime_runHeapTasks(JNIEnv* env, jobject) { Runtime::Current()->GetHeap()->GetTaskProcessor()->RunAllTasks(ThreadForEnv(env)); //开始执行守护线程的任务 }
#00 pc 000000000023418c /system/lib64/libart.so (art::gc::Heap::RequestTrim(art::Thread*)+100)
#01 pc 000000000024070c /system/lib64/libart.so (art::gc::Heap::CollectGarbageInternal(art::gc::collector::GcType, art::gc::GcCause, bool)+2280)
一般都是在回收垃圾后调用RequestTrim(),都是heap自己调用的,鲜少有从上层调用过来的,也许是我没发现吧
VMRuntime_concurrentGC() 和VMRuntime_requestConcurrentGC() 最终都是调用heap::ConcurrentGC() 只是过程稍有不同
class Heap { // Does a concurrent GC, should only be called by the GC daemon thread through runtime. void ConcurrentGC(Thread* self, bool force_full) LOCKS_EXCLUDED(Locks::runtime_shutdown_lock_); // Task processor, proxies heap trim requests to the daemon threads. std::unique_ptr<TaskProcessor> task_processor_; }
执行的任务放在task_processor_中,然后由守护线程去执行
void Heap::RequestConcurrentGC(Thread* self, bool force_full) { if (CanAddHeapTask(self) && concurrent_gc_pending_.CompareExchangeStrongSequentiallyConsistent(false, true)) { task_processor_->AddTask(self, new ConcurrentGCTask(NanoTime(), // Start straight away. force_full)); } } class Heap::ConcurrentGCTask : public HeapTask { public: explicit ConcurrentGCTask(uint64_t target_time, bool force_full) : HeapTask(target_time), force_full_(force_full) { } virtual void Run(Thread* self) OVERRIDE { gc::Heap* heap = Runtime::Current()->GetHeap(); // call ConcurrentGC() heap->ConcurrentGC(self, force_full_); heap->ClearConcurrentGCRequest(); } private: const bool force_full_; // If true, force full (or partial) collection. };
守护线程HeapTaskDaemon的起始
HeapTaskDaemon.start()部分代码参考 http://www.cnblogs.com/muhe221/articles/4711380.html
libcore/libart/src/main/java/java/lang/Daemons.java public final class Daemons { private static abstract class Daemon implements Runnable { private Thread thread; private String name; protected Daemon(String name) { this.name = name; } public synchronized void start() { if (thread != null) { throw new IllegalStateException("already running"); } thread = new Thread(ThreadGroup.systemThreadGroup, this, name); thread.setDaemon(true); thread.start(); } public abstract void run(); /** * Returns true while the current thread should continue to run; false * when it should return. */ protected synchronized boolean isRunning() { return thread != null; } public synchronized void interrupt() { interrupt(thread); } public synchronized void interrupt(Thread thread) { if (thread == null) { throw new IllegalStateException("not running"); } thread.interrupt(); } /** * Waits for the runtime thread to stop. This interrupts the thread * currently running the runnable and then waits for it to exit. */ public void stop() { Thread threadToStop; synchronized (this) { threadToStop = thread; thread = null; } if (threadToStop == null) { throw new IllegalStateException("not running"); } interrupt(threadToStop); while (true) { try { threadToStop.join(); return; } catch (InterruptedException ignored) { } } } }
/**
* This heap management thread moves elements from the garbage collector's
* pending list to the managed reference queue.
*/
private static class ReferenceQueueDaemon extends Daemon {
private static final ReferenceQueueDaemon INSTANCE = new ReferenceQueueDaemon();
ReferenceQueueDaemon() {
super("ReferenceQueueDaemon");
}
@Override public void run() {
while (isRunning()) {
Reference<?> list;
try {
synchronized (ReferenceQueue.class) {
while (ReferenceQueue.unenqueued == null) {
ReferenceQueue.class.wait();
}
list = ReferenceQueue.unenqueued;
ReferenceQueue.unenqueued = null;
}
} catch (InterruptedException e) {
continue;
}
enqueue(list);
}
}
private void enqueue(Reference<?> list) {
Reference<?> start = list;
do {
// pendingNext is owned by the GC so no synchronization is required.
Reference<?> next = list.pendingNext;
list.pendingNext = null;
list.enqueueInternal();
list = next;
} while (list != start);
}
}
//提供了两个方法,不是被java调用的,它是被external/v8/src/heap/incremental-marking.cc通过反射调用的
//比如分配内存后如果堆空闲内存太多则会调用requestHeapTrim
// Adds a heap trim task ot the heap event processor, not called from java. Left for
// compatibility purposes due to reflection.
public static void requestHeapTrim() {
VMRuntime.getRuntime().requestHeapTrim(); //注意:VMRuntime.getRuntime() 返回的是VMRuntime对象,而不是Runtime
}
// Adds a concurrent GC request task ot the heap event processor, not called from java. Left
// for compatibility purposes due to reflection.
public static void requestGC() {
VMRuntime.getRuntime().requestConcurrentGC();
} // HeapTaskDaemon is used to call TaskProcessor::RunAllTasks() private static class HeapTaskDaemon extends Daemon { private static final HeapTaskDaemon INSTANCE = new HeapTaskDaemon(); HeapTaskDaemon() { super("HeapTaskDaemon"); } // Overrides the Daemon.interupt method which is called from Daemons.stop. public synchronized void interrupt(Thread thread) { VMRuntime.getRuntime().stopHeapTaskProcessor(); } @Override public void run() { synchronized (this) { if (isRunning()) { // Needs to be synchronized or else we there is a race condition where we start // the thread, call stopHeapTaskProcessor before we start the heap task // processor, resulting in a deadlock since startHeapTaskProcessor restarts it // while the other thread is waiting in Daemons.stop(). VMRuntime.getRuntime().startHeapTaskProcessor(); } } // This runs tasks until we are stopped and there is no more pending task. VMRuntime.getRuntime().runHeapTasks();/////////开始循环并执行队列中的任务 } } }
目前看来只有这个位置调用requestGc()
// external/v8/src/heap/incremental-marking.cc
void IncrementalMarking::MarkingComplete(CompletionAction action) { state_ = COMPLETE; // We will set the stack guard to request a GC now. This will mean the rest // of the GC gets performed as soon as possible (we can't do a GC here in a // record-write context). If a few things get allocated between now and then // that shouldn't make us do a scavenge and keep being incremental, so we set // the should-hurry flag to indicate that there can't be much work left to do. set_should_hurry(true); if (FLAG_trace_incremental_marking) { PrintF("[IncrementalMarking] Complete (normal).\n"); } if (action == GC_VIA_STACK_GUARD) { heap_->isolate()->stack_guard()->RequestGC(); } }
目前看来是其它位置通过这个方法id来调用的
well_known_classes.cc 250 java_lang_Daemons_requestHeapTrim = CacheMethod(env, java_lang_Daemons, true, "requestHeapTrim", "()V");
class Daemons {
public static void requestHeapTrim() { VMRuntime.getRuntime().requestHeapTrim(); }
}
VMRuntime.getRuntime().requestHeapTrim() => 通过JNI调用(这里不赘述)=>Heap::RequestTrim() 其实RequestTrim()也是往task_processor_里面添加gc任务让守护线程执行
void Heap::RequestTrim(Thread* self) { if (!CanAddHeapTask(self)) { return; } // GC completed and now we must decide whether to request a heap trim (advising pages back to the // kernel) or not. Issuing a request will also cause trimming of the libc heap. As a trim scans // a space it will hold its lock and can become a cause of jank. // Note, the large object space self trims and the Zygote space was trimmed and unchanging since // forking. // We don't have a good measure of how worthwhile a trim might be. We can't use the live bitmap // because that only marks object heads, so a large array looks like lots of empty space. We // don't just call dlmalloc all the time, because the cost of an _attempted_ trim is proportional // to utilization (which is probably inversely proportional to how much benefit we can expect). // We could try mincore(2) but that's only a measure of how many pages we haven't given away, // not how much use we're making of those pages. HeapTrimTask* added_task = nullptr; { MutexLock mu(self, *pending_task_lock_); if (pending_heap_trim_ != nullptr) { // Already have a heap trim request in task processor, ignore this request. return; } added_task = new HeapTrimTask(kHeapTrimWait); pending_heap_trim_ = added_task; } task_processor_->AddTask(self, added_task); }
// libcore/libart/src/main/java/dalvik/system/VMRuntime.java public native void runHeapTasks(); // art/runtime/native/dalvik_system_VMRuntime.cc static void VMRuntime_runHeapTasks(JNIEnv* env, jobject) { Runtime::Current()->GetHeap()->GetTaskProcessor()->RunAllTasks(ThreadForEnv(env)); }
// art/runtime/gc/task_processor.cc
void TaskProcessor::Start(Thread* self) {
MutexLock mu(self, *lock_);
is_running_ = true;
running_thread_ = self;
}
void TaskProcessor::RunAllTasks(Thread* self) {
// 这里一直取任务执行 while (true) { // Wait and get a task, may be interrupted. HeapTask* task = GetTask(self); if (task != nullptr) { task->Run(self); task->Finalize(); } else if (!IsRunning()) { break; } } } void TaskProcessor::AddTask(Thread* self, HeapTask* task) { ScopedThreadStateChange tsc(self, kBlocked); MutexLock mu(self, *lock_); tasks_.insert(task); cond_->Signal(self); } HeapTask* TaskProcessor::GetTask(Thread* self) { ScopedThreadStateChange tsc(self, kBlocked); MutexLock mu(self, *lock_); while (true) { if (tasks_.empty()) { if (!is_running_) { return nullptr; } cond_->Wait(self); // Empty queue, wait until we are signalled. } else { // Non empty queue, look at the top element and see if we are ready to run it. const uint64_t current_time = NanoTime(); HeapTask* task = *tasks_.begin(); // If we are shutting down, return the task right away without waiting. Otherwise return the // task if it is late enough. uint64_t target_time = task->GetTargetRunTime(); if (!is_running_ || target_time <= current_time) { tasks_.erase(tasks_.begin()); return task; } DCHECK_GT(target_time, current_time); // Wait untl we hit the target run time. const uint64_t delta_time = target_time - current_time; const uint64_t ms_delta = NsToMs(delta_time); const uint64_t ns_delta = delta_time - MsToNs(ms_delta); cond_->TimedWait(self, static_cast<int64_t>(ms_delta), static_cast<int32_t>(ns_delta)); } } UNREACHABLE(); }
GC的守护线程:
1. ReferenceQueueDaemon:引用队列守护线程。我们知道,在创建引用对象的时候,可以关联一个队列。当被引用对象引用的对象被GC回收的时候,被引用对象就会被加入到其创建时关联的队列去。这个加入队列的操作就是由ReferenceQueueDaemon守护线程来完成的。这样应用程序就可以知道那些被引用对象引用的对象已经被回收了。
2. FinalizerDaemon:析构守护线程。对于重写了成员函数finalize的对象,它们被GC决定回收时,并没有马上被回收,而是被放入到一个队列中,等待FinalizerDaemon守护线程去调用它们的成员函数finalize,然后再被回收。
3. FinalizerWatchdogDaemon:析构监护守护线程。用来监控FinalizerDaemon线程的执行。一旦检测那些重定了成员函数finalize的对象在执行成员函数finalize时超出一定的时候,那么就会退出VM。
4. HeapTaskDaemon:堆裁剪守护线程。用来执行裁剪堆的操作,也就是用来将那些空闲的堆内存归还给系统。
GC 中可添加的任务类型以及被何种方式调用添加该task
// VMRuntime.java // public native void requestConcurrentGC(); class Heap::ConcurrentGCTask : public HeapTask {} // VMRuntime.java // public native void updateProcessState(int state); class Heap::CollectorTransitionTask : public HeapTask {} // VMRuntime.java // public native void requestHeapTrim(); class Heap::HeapTrimTask : public HeapTask {} // 这个Processor 主要用来清除其它gc完成后不使用的引用? class ClearedReferenceTask : public HeapTask {}
GC任务各自相关的Heap变量
calss Heap { // Task processor, proxies heap trim requests to the daemon threads. std::unique_ptr<TaskProcessor> task_processor_; // True while the garbage collector is running. volatile CollectorType collector_type_running_ GUARDED_BY(gc_complete_lock_); // 这个变量是指有没有requestConcurrentGC()请求 Atomic<bool> concurrent_gc_pending_; // 这个变量是指当前Heap中的CollectorTransitionTask任务,如果没有则为null CollectorTransitionTask* pending_collector_transition_; // 这个变量是指当前Heap中的HeapTrimTask任务,如果没有则为null HeapTrimTask* pending_heap_trim_; //ClearedReferenceTask和相关,ReferenceQueue ReferenceProcessor::cleared_references_ 记录了需要清除的引用 ReferenceProcessor reference_processor_; }
class Heap::ConcurrentGCTask : public HeapTask { public: explicit ConcurrentGCTask(uint64_t target_time, bool force_full) : HeapTask(target_time), force_full_(force_full) { } virtual void Run(Thread* self) OVERRIDE { gc::Heap* heap = Runtime::Current()->GetHeap(); heap->ConcurrentGC(self, force_full_); heap->ClearConcurrentGCRequest(); } private: const bool force_full_; // If true, force full (or partial) collection. }; class Heap::CollectorTransitionTask : public HeapTask { public: explicit CollectorTransitionTask(uint64_t target_time) : HeapTask(target_time) { } virtual void Run(Thread* self) OVERRIDE { gc::Heap* heap = Runtime::Current()->GetHeap(); heap->DoPendingCollectorTransition(); heap->ClearPendingCollectorTransition(self); } }; class Heap::HeapTrimTask : public HeapTask { public: explicit HeapTrimTask(uint64_t delta_time) : HeapTask(NanoTime() + delta_time) { } virtual void Run(Thread* self) OVERRIDE { gc::Heap* heap = Runtime::Current()->GetHeap(); heap->Trim(self); heap->ClearPendingTrim(self); } }; class ClearedReferenceTask : public HeapTask { public: explicit ClearedReferenceTask(jobject cleared_references) : HeapTask(NanoTime()), cleared_references_(cleared_references) { } virtual void Run(Thread* thread) { ScopedObjectAccess soa(thread); jvalue args[1]; args[0].l = cleared_references_; InvokeWithJValues(soa, nullptr, WellKnownClasses::java_lang_ref_ReferenceQueue_add, args); soa.Env()->DeleteGlobalRef(cleared_references_); } private: const jobject cleared_references_; };
----------------------------------------------------------------------------------------------------------------------
/libcore/libart/src/main/java/java/lang/Daemons.java
这个类主要是启动新的应用preFork()用来启动守护线程的,不会被普通的线程调用
/libcore/libart/src/main/java/dalvik/system/VMRuntime.java
其它线程通过VMRuntime来对Heap做相关的请求
public final class VMRuntime { public static VMRuntime getRuntime() { return THE_ONE; } /** * Gets the current ideal heap utilization, represented as a number * between zero and one. After a GC happens, the Dalvik heap may * be resized so that (size of live objects) / (size of heap) is * equal to this number. * * @return the current ideal heap utilization */ public native float getTargetHeapUtilization(); /** * Sets the current ideal heap utilization, represented as a number * between zero and one. After a GC happens, the Dalvik heap may * be resized so that (size of live objects) / (size of heap) is * equal to this number. * * <p>This is only a hint to the garbage collector and may be ignored. * * @param newTarget the new suggested ideal heap utilization. * This value may be adjusted internally. * @return the previous ideal heap utilization * @throws IllegalArgumentException if newTarget is <= 0.0 or >= 1.0 */ public float setTargetHeapUtilization(float newTarget) { if (newTarget <= 0.0f || newTarget >= 1.0f) { throw new IllegalArgumentException(newTarget + " out of range (0,1)"); } /* Synchronize to make sure that only one thread gets * a given "old" value if both update at the same time. * Allows for reliable save-and-restore semantics. */ synchronized (this) { float oldTarget = getTargetHeapUtilization(); nativeSetTargetHeapUtilization(newTarget); return oldTarget; } } /** * This method exists for binary compatibility. It is equivalent * to {@link System#runFinalization}. */ @Deprecated public void runFinalizationSync() { System.runFinalization(); } /** * Implements setTargetHeapUtilization(). * * @param newTarget the new suggested ideal heap utilization. * This value may be adjusted internally. */ private native void nativeSetTargetHeapUtilization(float newTarget); /** * This method exists for binary compatibility. It was part of * the external allocation API which was removed in Android 3.0 (Honeycomb). */ @Deprecated public boolean trackExternalAllocation(long size) { return true; } /** * This method exists for binary compatibility. It was part of * the external allocation API which was removed in Android 3.0 (Honeycomb). */ @Deprecated public void trackExternalFree(long size) {} /** * This method exists for binary compatibility. It was part of * the external allocation API which was removed in Android 3.0 (Honeycomb). */ @Deprecated public long getExternalBytesAllocated() { return 0; } /** * Tells the VM to enable the JIT compiler. If the VM does not have a JIT * implementation, calling this method should have no effect. */ public native void startJitCompilation(); /** * Tells the VM to disable the JIT compiler. If the VM does not have a JIT * implementation, calling this method should have no effect. */ public native void disableJitCompilation(); /** * Returns an array allocated in an area of the Java heap where it will never be moved. * This is used to implement native allocations on the Java heap, such as DirectByteBuffers * and Bitmaps. */ public native Object newNonMovableArray(Class<?> componentType, int length); /** * Returns an array of at least minLength, but potentially larger. The increased size comes from * avoiding any padding after the array. The amount of padding varies depending on the * componentType and the memory allocator implementation. */ public native Object newUnpaddedArray(Class<?> componentType, int minLength); /** * Returns the address of array[0]. This differs from using JNI in that JNI might lie and * give you the address of a copy of the array when in forcecopy mode. */ public native long addressOf(Object array); /** * Removes any growth limits, allowing the application to allocate * up to the maximum heap size. */ public native void clearGrowthLimit(); /** * Make the current growth limit the new non growth limit capacity by releasing pages which * are after the growth limit but before the non growth limit capacity. */ public native void clampGrowthLimit(); /** * Returns true if either a Java debugger or native debugger is active. */ public native boolean isDebuggerActive(); /** * Registers a native allocation so that the heap knows about it and performs GC as required. * If the number of native allocated bytes exceeds the native allocation watermark, the * function requests a concurrent GC. If the native bytes allocated exceeds a second higher * watermark, it is determined that the application is registering native allocations at an * unusually high rate and a GC is performed inside of the function to prevent memory usage * from excessively increasing. */ public native void registerNativeAllocation(int bytes); /** * Registers a native free by reducing the number of native bytes accounted for. */ public native void registerNativeFree(int bytes); /** * Wait for objects to be finalized. * * If finalization takes longer than timeout, then the function returns before all objects are * finalized. * * @param timeout * timeout in nanoseconds of the maximum time to wait until all pending finalizers * are run. If timeout is 0, then there is no timeout. Note that the timeout does * not stop the finalization process, it merely stops the wait. * * @see #Runtime.runFinalization() * @see #wait(long,int) */ public static void runFinalization(long timeout) { try { FinalizerReference.finalizeAllEnqueued(timeout); } catch (InterruptedException e) { // Interrupt the current thread without actually throwing the InterruptionException // for the caller. Thread.currentThread().interrupt(); } }
//上层只有两个地方可以间接调用concurrentGC() // 1.直接调用Heap::concurrentGC() // 2.通过requestConcurrentGC()在Heap::task_processor_中添加一个新的任务new ConcurrentGCTask() => Heap::concurrentGC() public native void requestConcurrentGC(); // 这个是以任务形式间接调用Heap::concurrentGC() public native void concurrentGC(); //这个是直接调用Heap::concurrentGC() public native void requestHeapTrim(); public native void trimHeap(); public native void startHeapTaskProcessor(); public native void stopHeapTaskProcessor(); public native void runHeapTasks(); // 这个是GC守护线程 /** * Let the heap know of the new process state. This can change allocation and garbage collection * behavior regarding trimming and compaction. */ public native void updateProcessState(int state); /** * Fill in dex caches with classes, fields, and methods that are * already loaded. Typically used after Zygote preloading. */ public native void preloadDexCaches(); }
VMRuntime::runHeapTasks() => TaskProcessor::RunAllTasks()
VMRuntime::startHeapTaskProcessor() => TaskProcessor::Start()
如果没执行start,则守护线程只执行一次gc后就退出了?
void TaskProcessor::Start(Thread* self) { MutexLock mu(self, *lock_); is_running_ = true; running_thread_ = self; } void TaskProcessor::RunAllTasks(Thread* self) { while (true) { // Wait and get a task, may be interrupted. HeapTask* task = GetTask(self); if (task != nullptr) { task->Run(self); task->Finalize(); } else if (!IsRunning()) { break; } } }
-------------------------------------------------------------------------------------------
CollectorTransitionTask
ART运行时的Foreground GC和Background GC,会执行CollectorTransitionTask任务
在HeapTaskDaemon执行的任务队列中添加CollectorTransitionTask
ActivityThread::setProcessState() => ActivityThread::updateProcessState() => VMRuntime.getRuntime().updateProcessState()
=> Runtime::Current()->GetHeap()->UpdateProcessState() => Heap::UpdateProcessState() => Heap::RequestCollectorTransition()
=> Heap::task_processor_->AddTask(self, new CollectorTransitionTask())
部分流程见 http://www.cnblogs.com/muhe221/articles/5271747.html
----------------------------------------------------------------
ImageReader.java 159 VMRuntime.getRuntime().registerNativeAllocation(mEstimatedNativeAllocBytes); Bitmap.java 1655 VMRuntime.getRuntime().registerNativeAllocation(mNativeAllocationByteCount); //art-code\art\runtime\native\dalvik_system_VMRuntime.cc Runtime::Current()->GetHeap()->RegisterNativeAllocation() Heap::RegisterNativeAllocation() => Heap::RunFinalization //Runtime.java public void runFinalization() { // 0 for no timeout. VMRuntime.runFinalization(0); } // libcore/libart/src/main/java/dalvik/system/VMRuntime.java public static void runFinalization(long timeout) { try { FinalizerReference.finalizeAllEnqueued(timeout); } catch (InterruptedException e) { // Interrupt the current thread without actually throwing the InterruptionException // for the caller. Thread.currentThread().interrupt(); } } // libcore/luni/src/main/java/java/lang/ref/FinalizerReference.java
registerNativeAllocation注册Native内存分配数时,就会触发java.lang.System类的静态成员函数runFinalization被调用,从而使得那些定义了成员函数finalize又即将被回收的对象执行成员函数finalize。