Android 12, <uses-library>
bağımlılıkları olan Java modülleri için DEX dosyalarının AOT derlemesinde (dexpreopt) yapı sistemi değişiklikleri içerir. Bazı durumlarda bu derleme sistemi değişiklikleri derlemeleri bozabilir. Kesintilere hazırlanmak için bu sayfayı kullanın ve bu sayfadaki tarifleri uygulayarak kesintileri düzeltin ve azaltın.
Dexpreopt, Java kitaplıklarının ve uygulamalarının önceden derlenmesi işlemidir. Dexpreopt, derleme sırasında ana makinede gerçekleşir (cihaz üzerinde gerçekleşen dexopt'un aksine). Java tarafından kullanılan paylaşılan kitaplık bağımlılıklarının yapısı modülünün (kitaplık veya uygulama), sınıf yükleyici bağlamı (CLC) olarak bilinir. Alıcı: dexpreopt, derleme zamanı ve çalışma zamanı CLC'lerinin doğruluğunu örtüştüğünden emin olun. Derleme zamanı CLC, dex2oat derleyicisinin dexpreopt zamanında kullandığı şeydir (ODEX dosyalarına kaydedilir) ve çalışma zamanı CLC, önceden derlenmiş kodun cihaza yüklendiği bağlamdır.
Hem doğruluk hem de performans açısından bu derleme zamanı ve çalışma zamanı CLC'leri çakışmalıdır. Doğruluk için yinelenen sınıfların ele alınması gerekir. Eğer çalışma zamanında paylaşılan kitaplık bağımlılıkları, bazı dersler farklı şekilde çözülebilir ve bu da sonuçta hataları da olabilir. Performans, yineleme için çalışma zamanı kontrollerinden de etkilenir. sınıflar.
Etkilenen kullanım alanları
İlk başlatma, bu değişikliklerden etkilenen ana kullanım alanıdır: ART derleme zamanı ile çalışma zamanı CLC'leri arasında bir uyumsuzluk tespit ederse dexpreopt'i reddeder çalışır ve dexopt'yi çalıştırır. Uygulamalar arka planda dexopt edilebilir ve diskte depolanabileceğinden sonraki önyüklemeler için bu sorun oluşturmaz.
Android'in etkilenen alanları
Bu durum, diğer Java kitaplıklarına çalışma zamanında bağımlı olan tüm Java uygulamalarını ve kitaplıklarını etkiler. Android'de binlerce uygulama var ve bu uygulamaların yüzlerce koordineli olacaklardır. Kendi kitaplıkları ve uygulamaları olan iş ortakları da bu durumdan etkilenir.
Zarar veren değişiklikler
Derleme sisteminin, dexpreopt derleme kurallarını oluşturmadan önce <uses-library>
bağımlılıkları bilmesi gerekir. Ancak derleme sistemi, derleme kuralları oluştururken (performans nedeniyle) rastgele dosyaları okumasına izin verilmediğinden doğrudan manifest dosyasına erişemez ve içindeki <uses-library>
etiketlerini okuyamaz. Ayrıca manifest, bir APK veya önceden derlenmiş bir paketin içine yerleştirilmiş olabilir. Bu nedenle, <uses-library>
bilgileri derleme dosyalarında (Android.bp
veya Android.mk
) bulunmalıdır.
Daha önce ART, paylaşılan kitaplık bağımlılıklarını (&-classpath
olarak bilinir) yok sayan bir geçici çözüm kullanıyordu. Bu çözüm güvenli değildi ve gözden kaçan hatalara neden olduğu için Android 12'de kaldırıldı.
Sonuç olarak doğru <uses-library>
sağlamayan Java modülleri
derleme dosyalarındaki bilgiler derleme kesintilerine neden olabilir (
derleme zamanı CLC uyuşmazlığı) veya ilk başlatma zamanı regresyonları (önyükleme zamanından kaynaklanan)
CLC uyuşmazlığı ve ardından dexopt).
Taşıma yolu
Bozuk bir yapıyı düzeltmek için şu adımları uygulayın:
Belirli bir ürün için derleme zamanı denetimini genel olarak devre dışı bırakın:
PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true
dosyasında bulunabilir. Bu işlem, derleme hatalarını düzeltir (Kırılmaları düzeltme bölümünde listelenen özel durumlar hariç). Ancak, bu geçici bir çözümdür ve başlatma zamanı CLC uyuşmazlığına neden olabilir ve ardından "dexopt" yazın.
Derleme zamanı denetimini genel olarak devre dışı bırakmadan önce başarısız olan modülleri düzeltin gerekli
<uses-library>
bilgilerini ekleyerek (ayrıntılar için Kesmeleri düzeltme bölümüne bakın). Çoğu modül için bu işlem,Android.bp
veyaAndroid.mk
dosyasına birkaç satır eklemeyi gerektirir.Derleme zamanı kontrolünü ve dexpreopt'i sorunlu durumlar için modül bazında devre dışı bırakın. Açılışta reddedilen yapıların derleme süresini ve depolama alanını boşa harcamamak için dexpreopt'u devre dışı bırakın.
Ayarı kaldırarak derleme zamanı denetimini genel olarak yeniden etkinleştir
PRODUCT_BROKEN_VERIFY_USES_LIBRARIES
(1. adımda ayarlanan), derleme olması gerektiğini unutmayın.3. adımda devre dışı bıraktığınız modülleri tek tek düzeltin, ardından dexpreopt ve
<uses-library>
kontrolünü yeniden etkinleştirin. Gerekirse hataları bildirin.
Derleme zamanı <uses-library>
kontrolleri Android 12'de zorunlu kılınır.
Kesintileri düzeltme
Aşağıdaki bölümlerde, belirli kesinti türlerinin nasıl düzeltileceği açıklanmaktadır.
Derleme hatası: CLC uyuşmazlığı
Derleme sistemi, sistemdeki bilgiler arasında
Android.bp
veya Android.mk
dosyalarını ve manifest dosyasını kullanabilirsiniz. Derleme sistemi okuyamıyor
ancak manifest'i okumak için derleme kuralları oluşturabilir (
(gerekirse bir APK'dan etiketleyip) ve manifest dosyasında <uses-library>
etiketlerini karşılaştırın
bu bilgileri derleme dosyalarındaki <uses-library>
bilgileriyle karşılaştırır. Kontrol başarısız olursa hata şu şekilde görünür:
error: mismatch in the <uses-library> tags between the build system and the manifest:
- required libraries in build system: []
vs. in the manifest: [org.apache.http.legacy]
- optional libraries in build system: []
vs. in the manifest: [com.x.y.z]
- tags in the manifest (.../X_intermediates/manifest/AndroidManifest.xml):
<uses-library android:name="com.x.y.z"/>
<uses-library android:name="org.apache.http.legacy"/>
note: the following options are available:
- to temporarily disable the check on command line, rebuild with RELAX_USES_LIBRARY_CHECK=true (this will set compiler filter "verify" and disable AOT-compilation in dexpreopt)
- to temporarily disable the check for the whole product, set PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true in the product makefiles
- to fix the check, make build system properties coherent with the manifest
- see build/make/Changes.md for details
Hata mesajında belirtildiği gibi, kullandığınız duruma bağlı olarak, aciliyet:
- Ürün genelinde geçici bir düzeltme için
Ürün oluşturma dosyasında
PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true
. Derleme zamanı tutarlılık kontrolü yine de yapılır ancak denetim hatası, bu bilgilerden faydalanabilirsiniz. Bunun yerine, kontrol hatası, derleme sisteminin dexpreopt'ta dex2oat derleyici filtresiniverify
olarak düşürmesine neden olur. Bu da AOT derlemeyi bu modül için tamamen devre dışı bırakır. - Hızlı ve genel bir komut satırı çözümü için
RELAX_USES_LIBRARY_CHECK=true
ortam değişkenini kullanın.PRODUCT_BROKEN_VERIFY_USES_LIBRARIES
ile aynı etkiye sahiptir ancak komut satırında kullanılmak üzere tasarlanmıştır. Çevre değişkeni, ürün değişkenini geçersiz kılar. - Hatanın kök neden düzeltilmesine yönelik bir çözüm bulmak için derleme sistemini,
manifest dosyasındaki
<uses-library>
etiketleridir. Hata mesajı incelendiğinde soruna hangi kitaplıkların neden olduğu gösterilir (AndroidManifest.xml
veya APK içindeki manifest incelendiğinde de bu bilgi gösterilir. Bu bilgiler, `aapt dump badging $APK | grep uses-library
` ile kontrol edilebilir).
Android.bp
modül için:
Eksik kitaplığı, modülün
libs
mülkünde bulun. Eğer genellikle bu tür kitaplıkları otomatik olarak ekler. özel durumlar:- Kitaplık bir SDK kitaplığı değildir (
java_sdk_library
yerinejava_library
olarak tanımlanır). - Kitaplığın kitaplık adı (manifest'te), modül adından (derleme sisteminde) farklı.
Bu sorunu geçici olarak düzeltmek için
provides_uses_lib: "<library-name>"
Android.bp
kitaplık tanımı. Uzun vadeli bir çözüm için altta yatan sorunu giderin sorun: kitaplığı SDK kitaplığına dönüştürün veya modülünü yeniden adlandırın.- Kitaplık bir SDK kitaplığı değildir (
Önceki adımda bir çözüm sağlanmadıysa modülün
Android.bp
tanımına zorunlu kitaplıklar içinuses_libs: ["<library-module-name>"]
veya isteğe bağlı kitaplıklar içinoptional_uses_libs: ["<library-module-name>"]
ekleyin. Bu tesisler bir listeyi kabul ediyor birkaç seçenek var. Listede kitaplıkların göreli sırası, manifest'teki sırayla aynı olmalıdır.
Android.mk
modülleri için:
Kitaplığın adından (manifest dosyasında) farklı bir kitaplık adı olup olmadığını kontrol edin. modül adı (derleme sisteminde). Bu durumda, kitaplığın
Android.mk
dosyasınaLOCAL_PROVIDES_USES_LIBRARY := <library-name>
ekleyerek veya kitaplığınAndroid.bp
dosyasınaprovides_uses_lib: "<library-name>"
ekleyerek bu sorunu geçici olarak düzeltin (Android.mk
modülü birAndroid.bp
kitaplığına bağlı olabileceğinden her iki durum da mümkündür). Uzun vadeli bir çözüm için temel sorunu düzeltin: Kitaplık modülünü yeniden adlandırın.Zorunlu için
LOCAL_USES_LIBRARIES := <library-module-name>
ekleyin kütüphaneler; şunun içinLOCAL_OPTIONAL_USES_LIBRARIES := <library-module-name>
ekleyin:Android.mk
tanımına isteğe bağlı kitaplıklar. Bu mülkler, modül adlarının listesini kabul eder. Listedeki kitaplıkların göreceli sırası, manifest'teki sırayla aynı olmalıdır.
Derleme hatası: Bilinmeyen kitaplık yolu
Derleme sistemi bir <uses-library>
DEX jar'ının yolunu (ana makinede derleme zamanı yolu veya cihazda yükleme yolu) bulamıyorsa genellikle derleme başarısız olur. Yolun bulunamaması, kitaplığın şurada yapılandırıldığını gösterebilir:
yol açabilir. Sorunlu modül için dexpreopt'u devre dışı bırakarak derlemeyi geçici olarak düzeltin.
Android.bp (modül özellikleri):
enforce_uses_libs: false,
dex_preopt: {
enabled: false,
},
Android.mk (modül değişkenleri):
LOCAL_ENFORCE_USES_LIBRARIES := false
LOCAL_DEX_PREOPT := false
Desteklenmeyen senaryoları incelemek için hata bildiriminde bulunun.
Derleme hatası: Kitaplık bağımlılığı eksik
Y modülünün manifest dosyasından Y derleme dosyasına <uses-library>
X ekleme girişimi, X bağımlılığının eksik olması nedeniyle derleme hatasına neden olabilir.
Aşağıda Android.bp modülleri için örnek bir hata mesajı verilmiştir:
"Y" depends on undefined module "X"
Aşağıda, Android.mk modülleri için örnek bir hata mesajı verilmiştir:
'.../JAVA_LIBRARIES/com.android.X_intermediates/dexpreopt.config', needed by '.../APPS/Y_intermediates/enforce_uses_libraries.status', missing and no known rule to make it
Bu tür hataların yaygın nedenlerinden biri, kitaplığın
ilgili modülün adı, derleme sisteminde yer alır. Örneğin, manifest dosyası
<uses-library>
girişi com.android.X
, ancak kitaplık modülünün adı
X
, hataya neden olur. Bu durumu çözmek için derleme sistemine X
adlı modülün com.android.X
adlı bir <uses-library>
sağladığını bildirin.
Aşağıda, Android.bp
kitaplıkları (modül özelliği) için bir örnek verilmiştir:
provides_uses_lib: “com.android.X”,
Aşağıda, Android.mk kitaplıkları (modül değişkeni) için bir örnek verilmiştir:
LOCAL_PROVIDES_USES_LIBRARY := com.android.X
Açılış zamanı CLC uyuşmazlığı
İlk açılışta, aşağıdaki gibi CLC uyuşmazlığıyla ilgili mesajlar için logcat'te arama yapın:
$ adb wait-for-device && adb logcat \
| grep -E 'ClassLoaderContext [a-z ]+ mismatch' -A1
Çıkış, burada gösterilen biçimde mesajlar içerebilir:
[...] W system_server: ClassLoaderContext shared library size mismatch Expected=..., found=... (PCL[]... | PCL[]...)
[...] I PackageDexOptimizer: Running dexopt (dexoptNeeded=1) on: ...
CLC uyuşmazlığı uyarısı alırsanız hatalı modül için dexopt komutunu arayın. Bu sorunu düzeltmek için modülün derleme zamanı kontrolünün geçtiğinden emin olun. Bu çözüm işe yaramazsa derleme sistemi tarafından desteklenmeyen özel bir durumla (ör. kitaplık yerine başka bir APK yükleyen bir uygulama) karşı karşıya olabilirsiniz. İlgili içeriği oluşturmak için kullanılan derleme sistemi tüm durumları ele almaz çünkü derleme zamanında uygulamanın çalışma zamanında ne yüklediğini bilebilir.
Sınıf yükleyici bağlamı
CLC, sınıf yükleyici hiyerarşisini açıklayan ağaç benzeri bir yapıdır. İlgili içeriği oluşturmak için kullanılan
derleme sistemi, CLC'yi dar anlamda kullanır (yalnızca kitaplıkları kapsar, APK'ları
özel sınıf yükleyiciler): Geçişli dönüşümleri temsil eden bir kütüphane ağacıdır
Bir kitaplık veya uygulamanın tüm <uses-library>
bağımlılıklarının kapatılması. Üst düzey
bir CLC'nin öğeleri, belirtilen doğrudan <uses-library>
bağımlılıklarıdır
değerini girin. CLC ağacının her düğümü, kendi <uses-library>
alt düğümlerine sahip olabilecek bir <uses-library>
düğümüdür.
Çünkü <uses-library>
bağımlılıkları yönlendirilmiş bir döngüsel grafiktir ve
CLC, aynı kitaplık için birden çok alt ağaç içerebilir. Diğer bir deyişle, CLC, bir ağaca "açılmış" bağımlılıklar grafiğidir. Kopyalama yalnızca mantıksal düzeydedir; temeldeki gerçek sınıf yükleyiciler kopyalanmaz (çalışma zamanında her kitaplık için tek bir sınıf yükleyici örneği vardır).
CLC, kitaplık veya uygulama tarafından kullanılan Java sınıflarını çözerken kitaplıkların arama sırasını tanımlar. Kitaplıklar yinelenen sınıflar içerebileceğinden ve sınıf ilk eşleşmeye göre çözüldüğünden arama sırası önemlidir.
Cihaz üzerinde (çalışma zamanı) CLC
PackageManager
(frameworks/base
ürününde) Java modülü yüklemek için bir CLC oluşturuyor
cihaz üzerinde. <uses-library>
etiketlerinde listelenen kitaplıkları, modülün manifest dosyasına üst düzey CLC öğeleri olarak ekler.
PackageManager
, kullanılan her kitaplık için tüm <uses-library>
değerlerini alır
bağımlılığı (ilgili kitaplığın manifest dosyasında etiketler olarak belirtilir) ve
iç içe yerleştirilmiş CLC'yi gösterir. Bu işlem, dönüşüm işlemi tamamlanana kadar
Oluşturulan CLC ağacının yaprak düğümleri, <uses-library>
içermeyen kitaplıklardır
ve bildirmeyi konuştuk.
PackageManager
, yalnızca paylaşılan kitaplıklardan haberdar olur. Bu kullanımda paylaşılanın tanımı, genel anlamından (ör. paylaşılan ve statik) farklıdır. Android'de Java paylaşılan kitaplıkları, cihaza yüklenen XML yapılandırmalarında listelenen kitaplıklardır (/system/etc/permissions/platform.xml
). Her giriş, paylaşılan bir kitaplığın adını, DEX jar dosyasının yolunu ve bağımlılıkların listesini (bu kitaplığın çalışma zamanında kullandığı ve manifest dosyasında <uses-library>
etiketlerinde belirttiği diğer paylaşılan kitaplıklar) içerir.
Diğer bir deyişle, PackageManager
uygulamasına olanak tanıyan iki bilgi kaynağı vardır
çalışma zamanında CLC oluşturmak için: manifest dosyasında <uses-library>
etiketleri ve
XML yapılandırmalarındaki paylaşılan kitaplık bağımlılıkları.
Ana makine üzerinde (derleme zamanı) CLC
CLC yalnızca bir kitaplık veya uygulama yüklerken gerekli değildir,
oluşturuyoruz. Derleme, cihaz üzerinde (dexopt) veya derleme sırasında (dexpreopt) yapılabilir. Dexopt cihaz üzerinde gerçekleştiği için PackageManager
ile aynı bilgilere (manifestler ve paylaşılan kitaplık bağımlılıkları) sahiptir.
Ancak Dexpreopt, ana makinede ve tamamen farklı bir ortamda gerçekleşir ve derleme sisteminden aynı bilgileri alması gerekir.
Bu nedenle, dexpreopt tarafından kullanılan derleme zamanı CLC ve
PackageManager
aynı şeydir ancak iki farklı şekilde hesaplanır.
Derleme zamanı ve çalışma zamanı CLC'leri eşleşmelidir. Aksi takdirde dexpreopt tarafından oluşturulan AOT derlenmiş kod reddedilir. Derleme zamanının eşitliğini kontrol etmek ve
çalışma zamanı CLC'leri, dex2oat derleyicisi, *.odex
dosyalarında derleme zamanı CLC'sini kaydeder
(OAT dosya başlığının classpath
alanında). Depolanan CLC'yi bulmak için şu komutu kullanın:
oatdump --oat-file=<FILE> | grep '^classpath = '
Derleme zamanı ve çalışma zamanı CLC uyuşmazlığı, önyükleme sırasında logcat'te bildirilir. Aşağıdaki komutu kullanarak arayın:
logcat | grep -E 'ClassLoaderContext [a-z ]+ mismatch'
Uyuşmazlık, kitaplığı veya uygulamayı veya optimizasyon olmadan çalışması (örneğin, uygulamanın kodu APK'nın bellekten çıkarılması gerekir. Bu çok pahalı bir işlemdir).
Paylaşılan kitaplık, isteğe bağlı veya zorunlu olabilir. dexpreopt açısından, gerekli bir kitaplık derleme zamanında mevcut olmalıdır (yokluğu derleme hatası olur). İsteğe bağlı bir kitaplık, derleme sırasında mevcut veya mevcut olmayabilir: Mevcutsa CLC'ye eklenir, dex2oat'a iletilir ve *.odex
dosyasına kaydedilir. İsteğe bağlı bir kitaplık yoksa atlanır ve CLC'ye eklenmez. Derleme zamanı ile RACI matrisleri arasında
çalışma zamanı durumu (isteğe bağlı kitaplık bir durumda mevcuttur, ancak diğerinde yoktur),
derleme zamanı ile çalışma zamanı CLC'leri eşleşmez ve derlenen kod
reddedildi.
Gelişmiş derleme sistemi ayrıntıları (manifest düzeltme aracı)
Bazen bir<uses-library>
kullanabilirsiniz. Örneğin, geçişli bağımlılıklardan biri müşterinin
başka bir <uses-library>
etiketi kullanmaya başlarsa ve
kitaplığın veya uygulamanın manifest dosyası, bunu içerecek şekilde güncellenmez.
Yakında, belirli bir kitaplık için eksik <uses-library>
etiketlerinden bazılarını hesaplayabilir
veya uygulamayı otomatik olarak (geçişli bağımlılık kapatmada SDK kitaplıkları olarak)
dokunun. Kitaplık (veya uygulama) ile ilgili bir sorun
SDK kitaplığına bağlı olan statik bir kitaplığa bağımlı olabilir.
yine geçişli olarak başka bir kitaplıktan geçer.
Tüm <uses-library>
etiketleri bu şekilde hesaplanamaz, ancak mümkünse
Shortg'un manifest girişlerini otomatik olarak eklemesine izin verilmelidir; daha az
ve bakımı basitleştirir. Örneğin, birçok uygulama statik
yeni bir <uses-library>
bağımlılığı ekleyen kitaplıksa, tüm uygulamalar
Bu da bakımı zor.