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 &lt;= 0.0 or &gt;= 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。

 

posted @ 2016-03-12 23:53  牧 天  阅读(18412)  评论(0编辑  收藏  举报