在開始之前,請先參閱 ART 服務的概要總覽。
自 Android 14 起,裝置端 AOT 編譯 應用程式 (又稱為 dexopt) 則由 ART 服務處理。ART 服務是 ART 的一部分 並透過系統屬性和 API 自訂模組。
系統屬性
ART 服務支援 dex2oat 選項。
此外,ART 服務支援下列系統屬性:
pm.dexopt。<reason>
這組系統屬性會決定預設編譯器篩選器 Dexopt 情境中所述的所有預先定義編譯原因。
若需更多資訊,請參閲 編譯器篩選器:
標準預設值如下:
pm.dexopt.first-boot=verify
pm.dexopt.boot-after-ota=verify
pm.dexopt.boot-after-mainline-update=verify
pm.dexopt.bg-dexopt=speed-profile
pm.dexopt.inactive=verify
pm.dexopt.cmdline=verify
pm.dexopt.shared (預設值:速度)
這是適用於其他應用程式所用應用程式的備用編譯器篩選器。
原則上,ART 服務會進行設定檔引導編譯 (speed-profile
),用於
所有應用程式。不過
其他應用程式使用的部分應用程式 (透過 <uses-library>
或已載入的應用程式)
方法是使用 Context#createPackageContext
,
CONTEXT_INCLUDE_CODE
)。這類應用程式無法使用本機
基於隱私權考量,影響個人資料或個人資料。
對於此類應用程式,如果要求設定檔引導編譯,ART 服務會先使用
嘗試使用雲端設定檔如果沒有雲端設定檔,ART Service
改回使用 pm.dexopt.shared
指定的編譯器篩選器。
如果要求的編譯作業並非設定檔指引,這個屬性就不會有任何作用。
pm.dexopt.<reason>.concurrency (預設值:1)
這是特定預先定義編譯作業的 dex2oat 叫用數量
原因 (first-boot
、boot-after-ota
、boot-after-mainline-update
和
bg-dexopt
)。
請注意,這個選項的效果會與
dex2oat 資源用量選項 (dalvik.vm.*dex2oat-threads
、
dalvik.vm.*dex2oat-cpu-set
和工作設定檔):
dalvik.vm.*dex2oat-threads
控管每個 dex2oat 的執行緒數量pm.dexopt.<reason>.concurrency
則控制 dex2oat 叫用。也就是說,並行執行緒數量上限為 這兩個系統屬性的乘積。dalvik.vm.*dex2oat-cpu-set
和工作設定檔一律會繫結 CPU 核心 無論並行執行緒數量上限為何 (已討論) )。
單一 dex2oat 叫用可能無法完全使用所有 CPU 核心,無論如何
(共 dalvik.vm.*dex2oat-threads
個)。因此,提高 dex2oat 數量
叫用 (pm.dexopt.<reason>.concurrency
) 就能更妥善地利用 CPU 核心,達到以下目的:
這能加快 dexopt 的整體進度這在
啟動。
不過,如果 dex2oat 叫用過多,可能會導致裝置
但可以透過將 dalvik.vm.dex2oat-swap
設為
true
允許使用替換檔案。叫用次數過多,
不需要切換環境因此,您應該仔細調整這個數字
按照各產品的需求分別處理
pm.dexopt.downGrade_after_inactive_days (預設:未設定)
如果設定這個選項,ART 服務只會使用最近指定的 天數。
此外,如果儲存空間即將用盡,在 dexopt 在背景執行 ART 服務
將未在前一個指定時間內未使用的應用程式降級
天數,以便釋出空間。這個問題的編譯器原因為 inactive
。
編譯器篩選器則取決於 pm.dexopt.inactive
聊天室
門檻是儲存空間管理工具的不足空間門檻
(可透過通用設定 sys_storage_threshold_percentage
和
sys_storage_threshold_max_bytes
,預設:500 MB) 再加上 500 MB。
如果透過
ArtManagerLocal#setBatchDexoptStartCallback
,清單中提供的套件
bg-dexopt
的 BatchDexoptStartCallback
指標絕不會降級。
pm.dexopt.disable_bg_dexopt (預設為 false)
僅供測試之用。這樣會防止 ART 服務安排背景排程 dexopt 工作
如果已安排背景執行 dexopt 工作,但尚未執行, 則不會有任何影響。也就是說,工作仍會執行。
避免背景 dexopt 工作 正在執行:
setprop pm.dexopt.disable_bg_dexopt true
pm bg-dexopt-job --disable
假如 尚未排定傳送時間第二行會解除背景 dexopt 工作排程 (如有) 且會立即取消背景 dexopt 工作 仍在執行中
ART 服務 API
ART 服務會公開 Java API 以進行自訂。API 的定義如下
ArtManagerLocal
。如需 Java 文件,請參閱
art/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
:
使用情形 (Android 14 來源、未發布的開發來源)。
ArtManagerLocal
是 LocalManagerRegistry
保管的單例模式。助手
函式 com.android.server.pm.DexOptHelper#getArtManagerLocal
可協助您
第一。
import static com.android.server.pm.DexOptHelper.getArtManagerLocal;
大多數 API 都需要 PackageManagerLocal.FilteredSnapshot
的例項。
中存放了所有應用程式的資訊你可以前往「撥打」
PackageManagerLocal#withFilteredSnapshot
,PackageManagerLocal
也是
由 LocalManagerRegistry
持有的單例模式,可從
com.android.server.pm.PackageManagerServiceUtils#getPackageManagerLocal
。
import static com.android.server.pm.PackageManagerServiceUtils.getPackageManagerLocal;
以下是一些 API 的一般用途。
針對應用程式觸發 dexopt 觸發程序
您可以隨時呼叫
ArtManagerLocal#dexoptPackage
。
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
getArtManagerLocal().dexoptPackage(
snapshot,
"com.google.android.calculator",
new DexoptParams.Builder(ReasonMapping.REASON_INSTALL).build());
}
您也可以傳遞自己的 dexopt 原因。這時將由優先順序類別和 編譯器篩選器必須明確設定
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
getArtManagerLocal().dexoptPackage(
snapshot,
"com.google.android.calculator",
new DexoptParams.Builder("my-reason")
.setCompilerFilter("speed-profile")
.setPriorityClass(ArtFlags.PRIORITY_BACKGROUND)
.build());
}
取消 dexopt
如果作業是由 dexoptPackage
呼叫啟動,您可以傳遞
表示您可以在某個時間點取消作業這可以
以非同步方式執行 dexopt 時
Executor executor = ...; // Your asynchronous executor here.
var cancellationSignal = new CancellationSignal();
executor.execute(() -> {
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
getArtManagerLocal().dexoptPackage(
snapshot,
"com.google.android.calculator",
new DexoptParams.Builder(ReasonMapping.REASON_INSTALL).build(),
cancellationSignal);
}
});
// When you want to cancel the operation.
cancellationSignal.cancel();
您也可以取消 ART 服務啟動的背景 dexopt。
getArtManagerLocal().cancelBackgroundDexoptJob();
取得 dexopt 結果
如果作業是由 dexoptPackage
呼叫啟動,您就可以取得結果
傳回的值
DexoptResult result;
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
result = getArtManagerLocal().dexoptPackage(...);
}
// Process the result here.
...
在許多情況下,ART 服務也會自行啟動 dexopt 作業,例如:
背景 dexopt。如要監聽所有 dexopt 結果,無論是否執行這項作業
由 dexoptPackage
呼叫或 ART 服務發起,請使用
ArtManagerLocal#addDexoptDoneCallback
。
getArtManagerLocal().addDexoptDoneCallback(
false /* onlyIncludeUpdates */,
Runnable::run,
(result) -> {
// Process the result here.
...
});
第一個引數會決定是否只包含結果更新。如果 您只想監聽 dexopt 更新的套件,請將其設為 true。
第二個引數是回呼的執行程式。如要在
執行 dexopt 的相同執行緒,請使用 Runnable::run
。如果您不想
回呼封鎖 dexopt,請使用非同步執行程式。
您可以新增多個回呼,讓 ART 服務執行所有回呼 所有回呼都將繼續運作,以供日後所有呼叫使用,除非 選擇移除
如要移除回呼,請在執行以下動作時保留回呼的參考資料:
新增,並使用 ArtManagerLocal#removeDexoptDoneCallback
。
DexoptDoneCallback callback = (result) -> {
// Process the result here.
...
};
getArtManagerLocal().addDexoptDoneCallback(
false /* onlyIncludeUpdates */, Runnable::run, callback);
// When you want to remove it.
getArtManagerLocal().removeDexoptDoneCallback(callback);
自訂套件清單和 dexopt 參數
ART 服務會在啟動和背景自行啟動 dexopt 作業
dexopt。如要自訂這些作業的套件清單或 dexopt 參數,請
使用 ArtManagerLocal#setBatchDexoptStartCallback
。
getArtManagerLocal().setBatchDexoptStartCallback(
Runnable::run,
(snapshot, reason, defaultPackages, builder, cancellationSignal) -> {
switch (reason) {
case ReasonMapping.REASON_BG_DEXOPT:
var myPackages = new ArrayList<String>(defaultPackages);
myPackages.add(...);
myPackages.remove(...);
myPackages.sort(...);
builder.setPackages(myPackages);
break;
default:
// Ignore unknown reasons.
}
});
你可以將商品加入包裹清單、移除項目、排序, 使用完全不同的清單
您的回呼必須忽略未知的原因,因為 未來的發展方向
最多只能設定一個BatchDexoptStartCallback
。回呼會保留
。
如要清除回呼,請使用
ArtManagerLocal#clearBatchDexoptStartCallback
。
getArtManagerLocal().clearBatchDexoptStartCallback();
自訂背景 dexopt 工作的參數
根據預設,在裝置處於閒置狀態時,背景 dexopt 工作每天會執行一次
以及充電此功能可透過以下方式變更:
ArtManagerLocal#setScheduleBackgroundDexoptJobCallback
。
getArtManagerLocal().setScheduleBackgroundDexoptJobCallback(
Runnable::run,
builder -> {
builder.setPeriodic(TimeUnit.DAYS.toMillis(2));
});
最多只能設定一個ScheduleBackgroundDexoptJobCallback
。回呼會
。除非你清除密碼,否則日後所有通話都將保持啟用狀態。
如要清除回呼,請使用
ArtManagerLocal#clearScheduleBackgroundDexoptJobCallback
。
getArtManagerLocal().clearScheduleBackgroundDexoptJobCallback();
暫時停用 dexopt
凡是由 ART 服務啟動的 dexopt 作業,都會觸發
BatchDexoptStartCallback
。只要您持續取消作業,
有效地停用 dexopt。
如果是取消背景 dexopt 的作業,則請遵循預設 重試政策 (30 秒,以指數表示,上限 5 小時)。
// Good example.
var shouldDisableDexopt = new AtomicBoolean(false);
getArtManagerLocal().setBatchDexoptStartCallback(
Runnable::run,
(snapshot, reason, defaultPackages, builder, cancellationSignal) -> {
if (shouldDisableDexopt.get()) {
cancellationSignal.cancel();
}
});
// Disable dexopt.
shouldDisableDexopt.set(true);
getArtManagerLocal().cancelBackgroundDexoptJob();
// Re-enable dexopt.
shouldDisableDexopt.set(false);
您最多只能有一個BatchDexoptStartCallback
。如果您也想使用
BatchDexoptStartCallback
用於自訂套件清單或 dexopt 參數,
必須將程式碼合併為一個回呼。
// Bad example.
// Disable dexopt.
getArtManagerLocal().unscheduleBackgroundDexoptJob();
// Re-enable dexopt.
getArtManagerLocal().scheduleBackgroundDexoptJob();
在應用程式安裝時執行的 dexopt 作業「不是」ART 啟動
售後服務而是由套件管理員透過
dexoptPackage
呼叫。因此「不會」觸發動作
BatchDexoptStartCallback
。如要停用應用程式安裝時的 dexopt,請防止
呼叫 dexoptPackage
的套件管理工具。
覆寫特定套件 (Android 15 以上版本) 的編譯器篩選器
您可以註冊
回呼 setAdjustCompilerFilterCallback
。系統會呼叫回呼
每當 dexopt 啟動
在啟動和背景 dexopt 或 dexoptPackage
API 呼叫期間的 ART 服務。
如果套件不需要調整,回呼必須傳回
originalCompilerFilter
。
getArtManagerLocal().setAdjustCompilerFilterCallback(
Runnable::run,
(packageName, originalCompilerFilter, reason) -> {
if (isVeryImportantPackage(packageName)) {
return "speed-profile";
}
return originalCompilerFilter;
});
您只能設定一個AdjustCompilerFilterCallback
。如要使用
AdjustCompilerFilterCallback
用於覆寫多個版本的編譯器篩選器
套件,您必須將程式碼合併為一個回呼。回呼會保留
。
如要清除回呼,請使用
ArtManagerLocal#clearAdjustCompilerFilterCallback
。
getArtManagerLocal().clearAdjustCompilerFilterCallback();
其他自訂項目
ART 服務也支援其他某些自訂設定。
設定背景 dexopt 的熱閾值
背景 dexopt 工作的熱控制是由工作排程器執行。
並在溫度達到上限時立即取消工作
THERMAL_STATUS_MODERATE
。如果
「THERMAL_STATUS_MODERATE
」可調整。
判斷 dexopt 是否正在執行 dexopt 背景
背景 dexopt 工作由 Job Scheduler 管理,其工作 ID 為
27873780
。如要判斷工作是否正在執行,請使用 Job Scheduler API。
// Good example.
var jobScheduler =
Objects.requireNonNull(mContext.getSystemService(JobScheduler.class));
int reason = jobScheduler.getPendingJobReason(27873780);
if (reason == PENDING_JOB_REASON_EXECUTING) {
// Do something when the job is running.
...
}
// Bad example.
var backgroundDexoptRunning = new AtomicBoolean(false);
getArtManagerLocal().setBatchDexoptStartCallback(
Runnable::run,
(snapshot, reason, defaultPackages, builder, cancellationSignal) -> {
if (reason.equals(ReasonMapping.REASON_BG_DEXOPT)) {
backgroundDexoptRunning.set(true);
}
});
getArtManagerLocal().addDexoptDoneCallback(
false /* onlyIncludeUpdates */,
Runnable::run,
(result) -> {
if (result.getReason().equals(ReasonMapping.REASON_BG_DEXOPT)) {
backgroundDexoptRunning.set(false);
}
});
if (backgroundDexoptRunning.get()) {
// Do something when the job is running.
...
}
提供 dexopt 的設定檔
如要使用設定檔引導 dexopt,請將 .prof
檔案或 .dm
檔案放在
APK。
.prof
檔案必須是二進位格式設定檔,且檔案名稱必須
APK 檔案名稱 + .prof
。例如:
base.apk.prof
.dm
檔案的檔案名稱必須是
擴充功能已由 .dm
取代。例如:
base.dm
如要驗證設定檔是否用於 dexopt,請使用下列指令執行 dexopt 指令
請speed-profile
並查看結果。
pm art clear-app-profiles <package-name>
pm compile -m speed-profile -f -v <package-name>
第一行會清除執行階段產生的所有設定檔 (也就是
/data/misc/profiles
) (如果有的話),確保 APK 旁邊的設定檔
ART Service 可能使用的唯一設定檔。第二行執行 dexopt
呼叫 speed-profile
,並傳遞 -v
來列印詳細結果。
如果使用設定檔,這個設定檔會顯示 actualCompilerFilter=speed-profile
結果。否則,您會看到 actualCompilerFilter=verify
。例如:
DexContainerFileDexoptResult{dexContainerFile=/data/app/~~QR0fTV0UbDbIP1Su7XzyPg==/com.google.android.gms-LvusF2uARKOtBbcaPHdUtQ==/base.apk, primaryAbi=true, abi=x86_64, actualCompilerFilter=speed-profile, status=PERFORMED, dex2oatWallTimeMillis=4549, dex2oatCpuTimeMillis=14550, sizeBytes=3715344, sizeBeforeBytes=3715344}
ART 服務不使用設定檔的常見原因包括:
- 設定檔的檔案名稱有誤,或是檔案不在 APK 旁邊。
- 設定檔格式錯誤。
- 設定檔與 APK 不符。(設定檔的總和檢查碼沒有
與 APK 中
.dex
檔案的總和檢查碼相符)。