Android 執行階段 (ART) 是執行 Android 裝置的預設執行階段 5.0 (API 級別 21) 以上版本。這個執行階段提供多種功能 。 如要進一步瞭解 ART 的新功能,請參閱「隆重推出 ART。
不過,某些 Dalvik 可用的技術無法在 ART 上運作。這個 這份文件會說明在 才能與 ART 相容。在使用指令列執行時, ART,
解決垃圾收集 (GC) 問題
在 Dalvik 底下,應用程式經常覺得明確呼叫
System.gc()
可提示垃圾收集 (GC)。這應該是
遠比使用 ART 需要得多,尤其在叫用垃圾收集時更是如此
避免包含 GC_FOR_ALLOC
類型的廣告
或減少片段您可以確認目前正在使用的執行階段
呼叫 System.getProperty("java.vm.version")
。如果 ART 使用中,屬性值
為 "2.0.0"
以上。
ART 使用並行複製 (CC) 收集器,後者會同時壓縮 Java 堆積。 因此,請避免同時使用 與壓縮 GC 不相容 (例如:將指標儲存至物件) 執行個體資料)。如果應用程式會使用 Java Native Interface (JNI)。詳情請參閱防範 JNI 問題。
防止 JNI 問題
ART 的 JNI 比 Dalvik 更嚴格。這是一個特別好的方法 並使用 CheckJNI 模式找出常見問題。如果應用程式使用 C/C++ 程式碼,您應查看以下文章:
偵錯 搭配 CheckJNI 使用的 Android JNI
檢查 JNI 程式碼是否有垃圾收集問題
並行複製 (CC) 收集器可能會移動記憶體中的物件以進行壓縮。 如果使用 C/C++ 程式碼,請勿使用 執行與精簡 GC 不相容的作業。我們強化了 檢查 JNI 找出一些潛在問題 (如 JNI 中所述) ICS 中的本機參考資料變更)。
特別留意的領域是
「Get...ArrayElements()
」和「Release...ArrayElements()
」
函式。在含有非密集 GC 的執行階段中
Get...ArrayElements()
函式通常會傳回對
實際記憶體支援陣列物件如果您變更其中一個
傳回的陣列元素,則陣列物件本身會變更 (而
至 Release...ArrayElements()
通常會遭到忽略)。不過,
如果使用精簡的 GC,Get...ArrayElements()
函式可能會
傳回記憶的副本如果您在壓縮 GC 時誤用了該參考資料:
否則可能會導致記憶體損毀或其他問題。例如:
- 如果您對傳回的陣列元素進行任何變更,就必須呼叫
並調整到適當的
Release...ArrayElements()
函式 以確保您所做的變更正確地複製回 陣列物件。 - 釋放記憶體陣列元素時,必須使用
模式,視您執行的變更而定:
- 如果您未變更陣列元素,請使用
JNI_ABORT
模式,會在未複製的情況下釋出記憶體 會變更回基礎陣列物件 - 如果您變更了陣列,且不需要該參照任何
此外,請使用程式碼
0
(更新陣列物件並釋出 就會產生這類訊息 - 如果您變更了要修訂的陣列,且希望
保留陣列副本,請使用
JNI_COMMIT
(更新的內容會更新) 並保留副本)。
- 如果您未變更陣列元素,請使用
- 呼叫
Release...ArrayElements()
時,會傳回相同的結果 原本由Get...ArrayElements()
傳回的指標。適用對象 舉例來說,遞增原始指標 (如要完整瀏覽 然後再將遞增的指標傳送至Release...ArrayElements()
。傳送這個修改的指標可能導致 導致記憶體損毀。
處理錯誤
在 Dalvik 沒有的情況下,ART 的 JNI 會擲回錯誤。(一次 您也可以用 CheckJNI 進行測試,藉此掌握許多這類情況。)
例如,如果使用以下方法呼叫 RegisterNatives
:
不存在 (原因可能是該方法已由如
ProGuard),ART 現在可以正確擲回 NoSuchMethodError
:
08-12 17:09:41.082 13823 13823 E AndroidRuntime: FATAL EXCEPTION: main 08-12 17:09:41.082 13823 13823 E AndroidRuntime: java.lang.NoSuchMethodError: no static or non-static method "Lcom/foo/Bar;.native_frob(Ljava/lang/String;)I" 08-12 17:09:41.082 13823 13823 E AndroidRuntime: at java.lang.Runtime.nativeLoad(Native Method) 08-12 17:09:41.082 13823 13823 E AndroidRuntime: at java.lang.Runtime.doLoad(Runtime.java:421) 08-12 17:09:41.082 13823 13823 E AndroidRuntime: at java.lang.Runtime.loadLibrary(Runtime.java:362) 08-12 17:09:41.082 13823 13823 E AndroidRuntime: at java.lang.System.loadLibrary(System.java:526)
如果 RegisterNatives
無效,ART 也會記錄錯誤 (顯示在 logcat 中)
不使用方法呼叫:
W/art ( 1234): JNI RegisterNativeMethods: attempt to register 0 native methods for <classname>
此外,JNI 函式為 GetFieldID()
和
GetStaticFieldID()
現已正確擲回 NoSuchFieldError
而不是直接傳回空值同樣地,GetMethodID()
和
GetStaticMethodID()
現在可以正確擲回 NoSuchMethodError
。
這可能會導致 CheckJNI 失敗,原因是未處理的例外狀況或
原生程式碼的 Java 呼叫端擲回例外狀況。如此一來
尤其重要的是,使用 CheckJNI 模式測試與 ART 相容的應用程式。
ART 預期 JNI CallNonvirtual...Method()
方法的使用者
(例如 CallNonvirtualVoidMethod()
) 會使用方法的宣告
而非子類別。
避免堆疊大小問題
Dalvik 針對原生程式碼和 Java 程式碼使用不同的堆疊,具有預設的 Java
堆疊大小為 32 KB,且預設的原生堆疊大小為 1 MB。ART 具有統一的
以獲得更準確的位置。通常情況下,ART Thread
堆疊
應該與 Dalvik 的大小大致相同不過,如果您已明確設定
設定堆疊大小後,您可能需要為執行中的應用程式重新檢查這些值
ART,
- 在 Java 中,查看對指定明確堆疊的
Thread
建構函式呼叫 大小舉例來說,如果發生StackOverflowError
,就需要放大大小。 - 在 C/C++ 中,查看
pthread_attr_setstack()
和pthread_attr_setstacksize()
:如果執行緒也會透過以下方式執行 Java 程式碼 JNI。以下是應用程式嘗試呼叫 JNI 時記錄的錯誤範例AttachCurrentThread()
:F/art: art/runtime/thread.cc:435] Attempt to attach a thread with a too-small stack (16384 bytes)
物件模型變更
Dalvik 允許子類別錯誤地覆寫套件的私人方法。 在這種情況下,ART 會顯示警告:
Before Android 4.1, method void com.foo.Bar.quux() would have incorrectly overridden the package-private method in com.quux.Quux
如要覆寫其他套件中的類別方法,請宣告
public
或 protected
方法。
Object
現在有不公開欄位。反映不同領域的應用程式
都應小心不要嘗試查看
Object
的欄位。舉例來說,如果您要疊代類別
做為序列化架構的一部分,
Class.getSuperclass() == java.lang.Object.class
而不是繼續作業,直到方法傳回 null
為止。
Proxy InvocationHandler.invoke()
現在會在沒有發生的情況下接收 null
而非空白陣列此行為已經記錄下來,
在 Dalvik 中未正確處理。Mockito 較舊版本的
所以在使用 ART 進行測試時,請使用更新的 Mockito 版本。
修正 AOT 編譯問題
ART 的預先 (AOT) Java 編譯應適用於所有標準 Java
再也不是件繁重乏味的工作編譯作業是由 ART 的
dex2oat
工具;如果發生
安裝時「dex2oat
」,請向我們回報 (請參閱「回報問題」一節),以便我們盡快修復。
。請注意以下幾個問題:
- 與 Dalvik 相比,ART 在安裝時執行位元碼驗證作業更為嚴格。 Android 建構工具產生的程式碼應該沒有問題。不過, 後期處理工具 (尤其是執行模糊處理工具) 的 Dalvik 容許,但遭到 ART 拒絕的無效檔案。我們 與工具供應商合作,找出並修正這類問題。在許多情況下 最新版本的工具並重新產生 DEX 檔案,即可修正問題 如要解決關聯問題,可用 Apriori 這類關聯規則學習技術和演算法
- ART 驗證器會回報的一些常見問題包括:
- 控制流程無效
- 不平衡
monitorenter
/monitorexit
- 0 長度參數類型清單大小
- 部分應用程式在已安裝的
.odex
檔案中有依附元件 格式為/system/framework
、/data/dalvik-cache
或 位於DexClassLoader
的最佳化輸出目錄中。這些 檔案現在是 ELF 檔案,而不是 DEX 的擴充檔案。ART 嘗試時 遵循與 Dalvik 相同的命名和鎖定規則,應用程式不應 檔案格式格式如有變更,恕不另行通知。注意:在 Android 8.0 (API 級別 26) 中, 較高,則
DexClassLoader
最佳化的輸出目錄 如需詳細資訊,請參閱DexClassLoader()
建構函式中設定。
報表問題
如果遇到非應用程式 JNI 問題以外的問題,請回報
並透過 Android 開放原始碼計畫 Issue Tracker (網址為 https://code.google.com/p/android/issues/list) 取得解決問題。
在 Google 網頁中加入 "adb bugreport"
和該應用程式的連結
Play 商店 (如有)。或者,如果可以,請附上重現的 APK
問題。請注意,問題 (包括附件) 是公開的
顯示。