Android System.gc()注意点

原创 2015年06月04日 17:18:08

背景

在看square Leakcanary源码时,发现这样一段话:

GcTrigger DEFAULT = new GcTrigger() {
    @Override public void runGc() {
      // Code taken from AOSP FinalizationTest:
      // https://android.googlesource.com/platform/libcore/+/master/support/src/test/java/libcore/
      // java/lang/ref/FinalizationTester.java
      // System.gc() does not garbage collect every time. Runtime.gc() is
      // more likely to perfom a gc.
      Runtime.getRuntime().gc();
      enqueueReferences();
      System.runFinalization(); 
}

跟进

到底有什么不一样呢?
我看了手头的4.2.2以及openjdk的源码:

public static void gc() {
        Runtime.getRuntime().gc();
}

System.gc()的实现就是调用Runtime.getRuntime().gc(),所以两者是等价的。所以这里是否是作者多虑了呢?我又看了一下5.0的源码,果然不一样了:


/**
 * Whether or not we need to do a GC before running the finalizers.
 */
  private static boolean runGC;

  /**
   * If we just ran finalization, we might want to do a GC to free the finalized objects.
   * This lets us do gc/runFinlization/gc sequences but prevents back to back System.gc().
   */
  private static boolean justRanFinalization;


/**
    * Provides a hint to the VM that it would be useful to attempt
    * to perform any outstanding object finalization.
    */
    public static void runFinalization() {
        boolean shouldRunGC;
        synchronized(lock) {
            shouldRunGC = runGC;
            runGC = false;
        }
        if (shouldRunGC) {
            Runtime.getRuntime().gc();
        }
        Runtime.getRuntime().runFinalization();
        synchronized(lock) {
            justRanFinalization = true;
        }
    }


 /**
   * Indicates to the VM that it would be a good time to run the
   * garbage collector. Note that this is a hint only. There is no guarantee
   * that the garbage collector will actually be run.
   */
  public static void gc() {
      boolean shouldRunGC;
      synchronized(lock) {
          shouldRunGC = justRanFinalization;
          if (shouldRunGC) {
              justRanFinalization = false;
        } else {
            runGC = true;
          }
    }
   if (shouldRunGC) {
          Runtime.getRuntime().gc();
   } 
}

这样改之后,单纯调用System.gc()是不会触发Runtime.getRuntime().gc()的。但是会把这次尝试纪录下来,等到下次调用System.runFinalization()时,会先执行这个Runtime.getRuntime().gc()。
这样改后的影响至少有两点:
1.单纯调用System.gc()是不会触发Runtime.getRuntime().gc()的,直到调用了System.runFinalization()
2.System.gc() -> System.gc() -> … -> System.gc() ->System.runFinalization(),最终只会调用一次Runtime.getRuntime().gc()

为什么要这样改呢?
找到了这个commit,是这样描述的:

Avoid running Runtime.gc() until we need to run finalization.

This prevents excessive explicit GC which are called from apps to get
good GC behavior on Dalvik. Calling System.gc() does not help on ART
since GC for alloc is much rarer.

If running finalizers is requested following a System.gc we remember
that a GC was requested and perform it ahead of finalization.

Bug: 12004934

从这里可以得到两点信息:
1.首先这是为了修复一个bug 12004934,具体什么bug找不到了
2.其次在art模式下,直接调用gc的效果不大。至于为什么,还没有深入进去了解,这是ART相关的另外一个专题了,后面再详细跟进。

回到开头,leakcanary的作者在这里直接用了Runtime.getRuntime().gc()的确是有理由的,但是这应该不是最好的方式,因为从这个提交的描述来看,连续调用Runtime.getRuntime().gc()可能存在bug。修改后的模式是gc / finalization / gc,虽然leakcanary这里的使用不会有问题。但是我觉得我们自己使用的话,用System.gc() 配合 System.runFinalization()会比较好。

Android核心技术——Android入门

-
  • 1970年01月01日 08:00

android垃圾回收机制及程序优化System.gc

android垃圾回收机制及程序优化System.gc By admin on 2013/07/20 1.垃圾收集算法的核心思想   Java语言建立了垃圾收集机制,用以跟踪正在使用的对...
  • wuqiong_524itcast
  • wuqiong_524itcast
  • 2014-05-09 11:32:21
  • 23096

Android开发之浅谈垃圾回收机制GC以及如何用好GC

本文转载自:http://www.cnblogs.com/jeffwongishandsome/p/talk-about-GC-and-how-to-use-GC-better.html,主要对GC知...
  • itluochen
  • itluochen
  • 2016-08-16 23:57:13
  • 7545

Android性能测试之内存泄露以及GC机制浅析(三)

Android 内存泄露以及GC机制浅析 今天来说说android当中的GC机制(garbage collector)...
  • Cloud_Huan
  • Cloud_Huan
  • 2015-11-27 16:20:09
  • 1264

调用System.gc没有立即执行的解决方法

查看源码当我们调用System.gc()的时候,其实并不会马上进行垃圾回收,甚至不一定会执行垃圾回收,查看系统源码可以看到 /** * Indicates to the VM tha...
  • yewei02538
  • yewei02538
  • 2016-08-31 16:49:35
  • 5687

Dalvik虚拟机垃圾收集(GC)过程分析

前面我们分析了Dalvik虚拟机堆的创建过程,以及Java对象在堆上的分配过程。这些知识都是理解Dalvik虚拟机垃圾收集过程的基础。垃圾收集是一个复杂的过程,它要将那些不再被引用的对象进行回收。一方...
  • Luoshengyang
  • Luoshengyang
  • 2014-12-22 01:00:40
  • 46511

android触发GC回收的条件

android触发垃圾回收的原因有以下5种: 1.当堆内存增长到一定程度时会触发。此时触发可以对堆中的没有用的对象及时进行回收,腾出空间供新的对象申请,避免进行不必要的增大堆内存的操作。 ...
  • joxpeng
  • joxpeng
  • 2015-04-09 17:39:16
  • 1739

android GC浅析

转载了自 http://blog.csdn.net/oujunli/article/details/12649017在dalvik中,GC的类型有三种: 1、GC_EXPLICIT: ...
  • myvest
  • myvest
  • 2016-10-13 15:07:37
  • 1390

System.gc(); 与Runtime.gc()的区别

(1) GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象...
  • TimMobile
  • TimMobile
  • 2015-10-27 19:37:16
  • 5354

android GC机制

Android的GC机制   GC:Garbage Collector   GC算法的核心思想 Android虚拟机采用根搜索算法和程序计数器算法。GC会从根节点(GC Roots)开始...
  • Junki_Lee
  • Junki_Lee
  • 2016-08-20 10:58:02
  • 729
收藏助手
不良信息举报
您举报文章:Android System.gc()注意点
举报原因:
原因补充:

(最多只允许输入30个字)