Başlamadan önce ART Hizmeti'ne genel bir bakış atın.
Android 14'ten itibaren, uygulamalar için cihaz üzerinde AOT derlemesi (diğer adıyla dexopt) ART Hizmeti tarafından yönetilir. ART Hizmeti, ART modülünün bir parçasıdır ve sistem özellikleri ile API'ler aracılığıyla özelleştirilebilir.
Sistem özellikleri
ART Hizmeti, ilgili tüm dex2oat seçeneklerini destekler.
Ayrıca ART Hizmeti aşağıdaki sistem özelliklerini destekler:
pm.dexopt.<reason>
Bu, Dexopt senaryolarında açıklanan tüm önceden tanımlanmış derleme nedenleri için varsayılan derleyici filtrelerini belirleyen bir sistem özellikleri grubudur.
Daha fazla bilgi için Derleyici filtreleri başlıklı makaleyi inceleyin.
Standart varsayılan değerler şunlardır:
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 (varsayılan: hız)
Bu, diğer uygulamalar tarafından kullanılan uygulamalar için yedek derleyici filtresidir.
ART Hizmeti, mümkün olduğunda (genellikle arka planda dexopt sırasında) tüm uygulamalar için profil odaklı derleme (speed-profile
) yapar. Ancak diğer uygulamalar tarafından kullanılan bazı uygulamalar vardır (<uses-library>
aracılığıyla veya CONTEXT_INCLUDE_CODE
ile Context#createPackageContext
kullanılarak dinamik olarak yüklenir). Bu tür uygulamalar, gizlilik nedeniyle yerel profilleri kullanamaz.
Bu tür bir uygulama için profil yönlendirmeli derleme istenirse ART Hizmeti önce bulut profilini kullanmayı dener. Bulut profili yoksa ART Hizmeti, pm.dexopt.shared
tarafından belirtilen derleyici filtresini kullanır.
İstenen derleme profil odaklı değilse bu özelliğin hiçbir etkisi olmaz.
pm.dexopt.<reason>.concurrency (varsayılan: 1)
Bu, belirli önceden tanımlanmış derleme nedenleri (first-boot
, boot-after-ota
, boot-after-mainline-update
ve bg-dexopt
) için dex2oat çağrılarının sayısıdır.
Bu seçeneğin etkisinin dex2oat kaynak kullanımı seçenekleriyle (dalvik.vm.*dex2oat-threads
, dalvik.vm.*dex2oat-cpu-set
ve görev profilleri) birleştirildiğini unutmayın:
dalvik.vm.*dex2oat-threads
, her dex2oat çağrısı için mesaj dizilerinin sayısını kontrol ederkenpm.dexopt.<reason>.concurrency
, dex2oat çağrılarının sayısını kontrol eder. Yani maksimum eşzamanlı ileti dizisi sayısı, iki sistem mülkünün çarpımıdır.dalvik.vm.*dex2oat-cpu-set
ve görev profilleri, eşzamanlı maksimum ileti dizisi sayısından (yukarıda ele alınmıştır) bağımsız olarak her zaman CPU çekirdek kullanımını sınırlandırır.
Tek bir dex2oat çağrısı, dalvik.vm.*dex2oat-threads
'ten bağımsız olarak tüm CPU çekirdeklerini tam olarak kullanamayabilir. Bu nedenle, dex2oat çağrılarının sayısını (pm.dexopt.<reason>.concurrency
) artırmak, dexopt'in genel ilerleme hızını artırmak için CPU çekirdeklerini daha iyi kullanabilir. Bu, özellikle önyükleme sırasında yararlıdır.
Ancak çok fazla dex2oat çağrısı yapılması, cihazın belleğinin tükenmesine neden olabilir. Bu durum, takas dosyasının kullanılmasına izin vermek için dalvik.vm.dex2oat-swap
değerini true
olarak ayarlayarak azaltılabilir. Çok fazla çağrı, gereksiz bağlam geçişlerine de neden olabilir. Bu nedenle, bu sayı ürüne göre dikkatlice ayarlanmalıdır.
pm.dexopt.downgrade_after_inactive_days (varsayılan: ayarlanmadı)
Bu seçenek ayarlanırsa ART Hizmeti yalnızca son belirtilen gün sayısı içinde kullanılan uygulamaların dexopt'unu kaldırır.
Ayrıca, depolama alanı neredeyse doluysa ART Hizmeti, arka planda dexopt işlemi sırasında yer açmak için son belirtilen gün sayısı içinde kullanılmayan uygulamaların derleyici filtresini düşürür. Bunun derleyici nedeni inactive
'tür ve derleyici filtresi pm.dexopt.inactive
tarafından belirlenir. Bu özelliği tetikleyen alan eşiği, Depolama Yöneticisi'nin düşük alan eşiği (sys_storage_threshold_percentage
ve sys_storage_threshold_max_bytes
genel ayarları üzerinden yapılandırılabilir, varsayılan: 500 MB) artı 500 MB'dır.
ArtManagerLocal#setBatchDexoptStartCallback
aracılığıyla paket listesini özelleştirirseniz BatchDexoptStartCallback
tarafından bg-dexopt
için sağlanan listedeki paketler hiçbir zaman düşürülmez.
pm.dexopt.disable_bg_dexopt (varsayılan: false)
Bu yalnızca test amaçlıdır. ART Hizmeti'nin arka planda dexopt görevini planlamasını engeller.
Arka planda dexopt işi zaten planlanmışsa ancak henüz çalıştırılmamışsa bu seçeneğin hiçbir etkisi olmaz. Yani iş çalışmaya devam eder.
Arka planda dexopt işinin çalışmasını önlemek için önerilen komut dizisi:
setprop pm.dexopt.disable_bg_dexopt true
pm bg-dexopt-job --disable
İlk satır, henüz planlanmamışsa arka planda dexopt işinin planlanmasını engeller. İkinci satır, önceden planlanmışsa arka planda dexopt işinin planlamasını iptal eder ve çalışıyorsa arka planda dexopt işini hemen iptal eder.
ART Hizmet API'leri
ART Hizmeti, özelleştirme için Java API'lerini gösterir. API'ler ArtManagerLocal
adresinde tanımlanır. Kullanım alanları için art/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
içindeki Javadoc'a bakın (Android 14 kaynağı, yayınlanmamış geliştirme kaynağı).
ArtManagerLocal
, LocalManagerRegistry
tarafından tutulan tekil bir öğedir. com.android.server.pm.DexOptHelper#getArtManagerLocal
yardımcı işlevi, bu değeri elde etmenize yardımcı olur.
import static com.android.server.pm.DexOptHelper.getArtManagerLocal;
API'lerin çoğu, tüm uygulamaların bilgilerini içeren bir PackageManagerLocal.FilteredSnapshot
örneği gerektirir. PackageManagerLocal#withFilteredSnapshot
çağrısı yaparak bu değeri alabilirsiniz. Burada PackageManagerLocal
, LocalManagerRegistry
tarafından tutulan ve com.android.server.pm.PackageManagerServiceUtils#getPackageManagerLocal
'dan alınabilen tekil bir değerdir.
import static com.android.server.pm.PackageManagerServiceUtils.getPackageManagerLocal;
Aşağıda, API'lerin bazı tipik kullanım alanları verilmiştir.
Bir uygulama için dexopt'i tetikleme
ArtManagerLocal#dexoptPackage
işlevini çağırarak istediğiniz zaman herhangi bir uygulama için dexopt'u tetikleyebilirsiniz.
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
getArtManagerLocal().dexoptPackage(
snapshot,
"com.google.android.calculator",
new DexoptParams.Builder(ReasonMapping.REASON_INSTALL).build());
}
Ayrıca kendi dexopt nedeninizi de iletebilirsiniz. Bu durumda, öncelik sınıfı ve derleyici filtresi açıkça ayarlanmalıdır.
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'u iptal etme
Bir işlem dexoptPackage
çağrısıyla başlatılırsa işlemi herhangi bir noktada iptal etmenize olanak tanıyan bir iptal sinyali iletebilirsiniz. Bu, dexopt'u eşzamansız olarak çalıştırdığınızda yararlı olabilir.
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 Hizmeti tarafından başlatılan arka planda dexopt işlemini de iptal edebilirsiniz.
getArtManagerLocal().cancelBackgroundDexoptJob();
dexopt sonuçlarını alma
Bir işlem dexoptPackage
çağrısıyla başlatılırsa sonucu döndürülen değerden alabilirsiniz.
DexoptResult result;
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
result = getArtManagerLocal().dexoptPackage(...);
}
// Process the result here.
...
ART Hizmeti, arka planda dexopt işlemi gibi birçok senaryoda dexopt işlemlerini kendisi de başlatır. İşlem dexoptPackage
çağrısı veya ART Hizmeti tarafından başlatılmış olsun, tüm dexopt sonuçlarını dinlemek için ArtManagerLocal#addDexoptDoneCallback
kullanın.
getArtManagerLocal().addDexoptDoneCallback(
false /* onlyIncludeUpdates */,
Runnable::run,
(result) -> {
// Process the result here.
...
});
İlk bağımsız değişken, sonuca yalnızca güncellemelerin dahil edilip edilmeyeceğini belirler. Yalnızca dexopt tarafından güncellenen paketleri dinlemek istiyorsanız bu değeri true olarak ayarlayın.
İkinci bağımsız değişken, geri çağırma işlevinin yürütücüsüdür. Geri çağırma işlevini, dexopt işlemini gerçekleştiren aynı iş parçacığında yürütmek için Runnable::run
kullanın. Geri çağırma işlevinin dexopt'u engellemesini istemiyorsanız asynkron bir yürütücü kullanın.
Birden fazla geri çağırma ekleyebilirsiniz. ART Hizmeti, bunların tümünü sırayla yürütür. Kaldırmadığınız sürece tüm geri aramalar gelecekteki tüm aramalar için etkin kalır.
Geri aramayı kaldırmak istiyorsanız geri aramayı eklerken referansını saklayın ve ArtManagerLocal#removeDexoptDoneCallback
kullanın.
DexoptDoneCallback callback = (result) -> {
// Process the result here.
...
};
getArtManagerLocal().addDexoptDoneCallback(
false /* onlyIncludeUpdates */, Runnable::run, callback);
// When you want to remove it.
getArtManagerLocal().removeDexoptDoneCallback(callback);
Paket listesini ve dexopt parametrelerini özelleştirme
ART Hizmeti, önyükleme ve arka planda dexopt sırasında dexopt işlemlerini kendisi başlatır. Bu işlemler için paket listesini veya dexopt parametrelerini özelleştirmek üzere ArtManagerLocal#setBatchDexoptStartCallback
kullanın.
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.
}
});
Paket listesine öğe ekleyebilir, listeden öğe kaldırabilir, listeyi sıralayabilir veya tamamen farklı bir liste kullanabilirsiniz.
Gelecekte daha fazla neden eklenebilir. Bu nedenle, geri arama işleminizde bilinmeyen nedenler yoksayılmalıdır.
En fazla bir BatchDexoptStartCallback
ayarlayabilirsiniz. Geri arama, siz silmediğiniz sürece gelecekteki tüm aramalar için etkin kalır.
Geri aramayı silmek için ArtManagerLocal#clearBatchDexoptStartCallback
simgesini kullanın.
getArtManagerLocal().clearBatchDexoptStartCallback();
Arka planda dexopt işinin parametrelerini özelleştirme
Varsayılan olarak arka planda dexopt işi, cihaz boştayken ve şarj olurken günde bir kez çalışır. Bu ayar ArtManagerLocal#setScheduleBackgroundDexoptJobCallback
kullanılarak değiştirilebilir.
getArtManagerLocal().setScheduleBackgroundDexoptJobCallback(
Runnable::run,
builder -> {
builder.setPeriodic(TimeUnit.DAYS.toMillis(2));
});
En fazla bir ScheduleBackgroundDexoptJobCallback
ayarlayabilirsiniz. Geri arama, siz silmediğiniz sürece gelecekteki tüm aramalar için etkin kalır.
Geri aramayı silmek için ArtManagerLocal#clearScheduleBackgroundDexoptJobCallback
simgesini kullanın.
getArtManagerLocal().clearScheduleBackgroundDexoptJobCallback();
dexopt'u geçici olarak devre dışı bırakma
ART Hizmeti tarafından başlatılan tüm dexopt işlemleri bir BatchDexoptStartCallback
tetikler. dexopt'u etkili bir şekilde devre dışı bırakmak için işlemleri iptal etmeye devam edebilirsiniz.
İptal ettiğiniz işlem arka planda dexopt ise varsayılan yeniden deneme politikası (30 saniye, üstel, 5 saatle sınırlı) geçerli olur.
// 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);
En fazla bir BatchDexoptStartCallback
'ünüz olabilir. Paket listesini veya dexopt parametrelerini özelleştirmek için BatchDexoptStartCallback
'ü de kullanmak istiyorsanız kodu tek bir geri çağırma işlevinde birleştirmeniz gerekir.
// Bad example.
// Disable dexopt.
getArtManagerLocal().unscheduleBackgroundDexoptJob();
// Re-enable dexopt.
getArtManagerLocal().scheduleBackgroundDexoptJob();
Uygulama yüklemesinde gerçekleştirilen dexopt işlemi, ART Hizmeti tarafından başlatılmaz. Bunun yerine, paket yöneticisi tarafından bir dexoptPackage
çağrısı aracılığıyla başlatılır. Bu nedenle, BatchDexoptStartCallback
tetiklenmez. Uygulama yükleme sırasında dexopt'u devre dışı bırakmak için paket yöneticisinin dexoptPackage
çağrısını engelleyin.
Belirli paketler için derleyici filtresini geçersiz kılma (Android 15 ve sonraki sürümler)
setAdjustCompilerFilterCallback
aracılığıyla geri çağırma işlevi kaydederek belirli paketler için derleyici filtresini geçersiz kılabilirsiniz. Geri çağırma işlevi, bir paketin dexopt işlemine tabi tutulacağı her zaman çağrılır. Bu çağrı, dexopt işleminin ART Hizmeti tarafından önyükleme ve arka plan dexopt işlemi sırasında mı yoksa bir dexoptPackage
API çağrısı tarafından mı başlatıldığına bakılmaksızın gerçekleşir.
Bir paketin ayarlanması gerekmiyorsa geri çağırma işlevi originalCompilerFilter
döndürmelidir.
getArtManagerLocal().setAdjustCompilerFilterCallback(
Runnable::run,
(packageName, originalCompilerFilter, reason) -> {
if (isVeryImportantPackage(packageName)) {
return "speed-profile";
}
return originalCompilerFilter;
});
Yalnızca bir AdjustCompilerFilterCallback
ayarlayabilirsiniz. Birden fazla paket için derleyici filtresini geçersiz kılmak üzere AdjustCompilerFilterCallback
kullanmak istiyorsanız kodu tek bir geri çağırma işlevinde birleştirmeniz gerekir. Geri arama, siz silmediğiniz sürece gelecekteki tüm aramalar için etkin kalır.
Geri aramayı silmek için ArtManagerLocal#clearAdjustCompilerFilterCallback
simgesini kullanın.
getArtManagerLocal().clearAdjustCompilerFilterCallback();
Diğer özelleştirmeler
ART Hizmeti, diğer bazı özelleştirmeleri de destekler.
Arka planda dexopt için termal eşiği ayarlama
Arka planda dexopt işinin termal kontrolü İş Planlayıcı tarafından gerçekleştirilir.
Sıcaklık THERMAL_STATUS_MODERATE
'e ulaştığında iş hemen iptal edilir. THERMAL_STATUS_MODERATE
eşiği ayarlanabilir.
Arka planda dexopt'un çalışıp çalışmadığını belirleme
Arka planda dexopt işi İş Planlayıcı tarafından yönetilir ve iş kimliği 27873780
'tür. İşin çalışıp çalışmadığını belirlemek için Job Scheduler API'lerini kullanın.
// 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 için bir profil sağlayın
Dexopt'a rehberlik etmek için bir profil kullanmak istiyorsanız APK'nın yanına bir .prof
dosyası veya .dm
dosyası ekleyin.
.prof
dosyası ikili biçimli bir profil dosyası olmalı ve dosya adı, APK dosya adının .prof
ile birlikte yazılmış halidir. Örneğin,
base.apk.prof
.dm
dosyasının adı, uzantısı .dm
ile değiştirilmiş APK dosyasının adıdır. Örneğin,
base.dm
Profilin dexopt için kullanıldığını doğrulamak üzere dexopt'u speed-profile
ile çalıştırın ve sonucu kontrol edin.
pm art clear-app-profiles <package-name>
pm compile -m speed-profile -f -v <package-name>
İlk satır, APK'nın yanındaki profilin ART Hizmeti'nin kullanabileceği tek profil olduğundan emin olmak için çalışma zamanı tarafından oluşturulan tüm profilleri (varsa /data/misc/profiles
içindekiler) temizler. İkinci satır, dexopt'u speed-profile
ile çalıştırır ve ayrıntılı sonucu yazdırmak için -v
parametresini iletir.
Profil kullanılıyorsa sonuçta actualCompilerFilter=speed-profile
simgesi gösterilir. Aksi takdirde actualCompilerFilter=verify
simgesini görürsünüz. Örneğin,
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 hizmetinin profili kullanmamasının yaygın nedenleri şunlardır:
- Profilin dosya adı yanlış veya APK'nın yanında değil.
- Profil yanlış biçimde.
- Profil, APK ile eşleşmiyor. (Profildeki sağlama toplamları, APK'daki
.dex
dosyalarının sağlama toplamlarıyla eşleşmiyor.)