1. 程式人生 > >Android System.gc()注意點

Android System.gc()注意點

背景

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 System.gc()注意

背景 GcTrigger DEFAULT = new GcTrigger() { @Override public void runGc() { // Code taken from AOSP FinalizationTest:

Android autoLink的注意

<TextView       android:layout_width="fill_parent"      android:layout_height="wrap_content"      android:text="請訪問: www.baidu.com" 

Android SQLiteDatabase使用注意

1、建立或刪除資料表:如:SQLiteDatabase test = SQLiteDatabase.openDatabase(LOG_DBPATH, null, SQLiteDatabase.OPEN_READWRITE | SQLiteDatabase.CREATE_IF_

[Android]一些細節注意和程式碼

隨時更新一些編寫應用中遇到的細節注意點 1 . 對返回鍵的處理,如實現長按返回鍵退出: @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode ==

Android Studio使用的那些事(三)AS不同版本安裝注意

繼上篇遷移整理了 Android Studio使用的那些事(二)AS常見錯誤 這篇將整理記錄Android Studio我在使用更新不同版本時候所遇到要注意的點。Android Studio當時的1.2、1.5 我就沒有記錄了,因為當時AS還不夠成熟問題還很多,雖然下載安裝了

關於urho3d中載入資源用法在Lua中一些注意 android

起因: 載入場景的做法是Lua函式匯出中使用的是File的形式,在android上無法取到正確的位置,但是cache:GetResource可以獲取到XMLFile所以需要進行修改 這裡修改的檔案 Node.pkg, Scene.pkg Node.h No

Android GC

想寫一篇關於Android GC的想法來源於追查一個魅族手機圖片滑動卡頓問題,由於不斷的GC導致的丟幀卡頓的問題讓我們想了很多方案去解決,所以就打算詳細的看看記憶體分配和GC的原理,為什麼會不斷的GC, GC ALLOC和GC COCURRENT有什麼區別,能不能想辦法擴大堆記憶體減少GC的頻次等等。

android接入華為推送注意

        由於公司產品有及時聊天功能,因此對資訊達到及時性要求比較高,因此安排我處理部分android手機在app不執行情況下的資訊推送。下面分別介紹華為推送和小米推送接入。        一、華為推送 接入之前,我先研究了華為推送的demo,目前華為推送官網是HMS

Android Studio 下使用自定義屬性注意

1.Eclipse 下使用自定義屬性 先要在res 下的value目錄下生成attr.xml中定義自己的屬性,例如下面 <?xml version="1.0" encoding="utf-8"?> <resources>

Android微信支付SDK的細微注意

首先這個demo是Eclipse專案,在用Eclipse匯入進來後會報"com.tencent.mm.sdk"這個路徑找不到,原因有2個: 1.wechat-sdk-android-with-mta的包沒有匯入,右鍵選中包,build path->add to l

Android利用微信SDK分享到微信教程,回撥分享結果錯誤解決和注意

在正式開始之前這裡要著囉嗦一下,進來的同學一定要看,在申請應用的時候要填一個簽名,這個簽名是由應用的簽名檔案keystore決定的,那麼你在填這個簽名的時候,一定要把你的應用用正式的keyStore生成apk,安裝到手機,然後用微信提供的獲取應用簽名的apk工具獲取你應用

Android中Service的使用詳解和注意(LocalService)

開始,先稍稍講一點android中Service的概念和用途吧~ Service分為本地服務(LocalService)和遠端服務(RemoteService): 1、本地服務依附在主程序上而不是獨立的程序,這樣在一定程度上節約了資源,另外Local服務因為是在同一程序因此

Android 防止記憶體洩漏的幾個注意

1)getSystemService的時候,應避免使用activity的context,而是使用application的context2)單例模式的context,應使用context.getApplicationContext來代替,如下:public class AppS

android關於 子控制元件超出父控制元件範圍的注意

通過 搜尋引擎的搜尋,我們知道了android:clipChildren = "false"  這個屬性 可以讓父view 在子view超出以後不切割子view。 那麼我現在說幾個注意點,如果你沒有注意這幾個點可能子view 超不出去。   android:clipC

第二十三篇 Android通過原生Api獲取經緯度以及百度定位注意

Android通過原生Api獲取經緯度: 原生定位API只能定位到經緯度,但是如果要定位具體的地址,則需要將經緯度資訊傳送到谷歌伺服器,進行反向地理位置解析,因為目前 國內無法連線谷歌伺服器,所以使用原生定位API就不合適了,而且百度定位的功能多又強,非常適合

Android 從具體例項分析Bitmap使用時候記憶體注意

根據Android官方提供給我們的Sample例子實實在在的分析Bitmap使用時候的注意點。 在分析Bitmap的使用之前先簡單的瞭解下BitmapFactory 類,BitmapFactory類可以根據各種不同的資料來源(檔案,流,位元組陣列等)來構建Bi

android垃圾回收機制及程式優化System.gc

1.垃圾收集演算法的核心思想   Java語言建立了垃圾收集機制,用以跟蹤正在使用的物件和發現並回收不再使用(引用)的物件。該機制可以有效防範動態記憶體分配中可能發生的兩個危險:因記憶體垃圾過多而引發的記憶體耗盡,以及不恰當的記憶體釋放所造成的記憶體非法引用。   垃圾收集演算法的核心思想是:對虛擬機器可用

每日一問:Android 中記憶體洩漏都有哪些注意

記憶體洩漏對每一位 Android 開發一定是司空見慣,大家或多或少都肯定有些許接觸。大家都知道,每一個手機都有一定的承載上限,多處的記憶體洩漏堆積一定會堆積如山,最終出現記憶體爆炸 OOM。 而這,也是極有可能在 Android 面試中一道常見的開放題。 記憶體洩漏的根本原因是一個長生命週期的物件持有了一個

Android嵌入式開發初學者的幾個注意

    一:首先你必須瞭解ARM平臺 Android 移植與驅動核心開發,當然也可以是X86和其他的平臺,不過其他平臺的Android智慧終端開發並不是很多。 Android嵌入式智慧作業系統是基於Linux核心和驅動的,對於HTC、華為等公司開發Android作業系統時,需要專門

System.out.printf使用以及注意

一、System.out.printf格式化輸出 1、常用控制符 控制符 說明 %d 按十進位制整型資料的實際長度輸出。 %ld 輸出長整型資料。 %md m 為指定的輸出欄位的寬度。如果資料的位數小於 m,則左端補以空格,若大於 m,則按實際位數輸出。