16 KB sayfa boyutlarını destekleme

Android, geçmişte yalnızca 4 KB bellek sayfası boyutlarını desteklemişti. Bu da Android cihazların genellikle sahip olduğu toplam bellek miktarı için sistem belleği performansını optimize etmişti. Android 15'ten itibaren AOSP, 16 KB sayfa boyutu kullanacak şekilde yapılandırılmış cihazları (16 KB cihazlar) destekler. Uygulamanız doğrudan veya bir SDK üzerinden dolaylı olarak NDK kitaplıkları kullanıyorsa uygulamanızı 16 KB'lık cihazlarda çalışacak şekilde yeniden oluşturmanız gerekir.

Cihaz üreticileri daha fazla fiziksel bellek (RAM) içeren cihazlar üretmeye devam ettikçe bu cihazların çoğu, cihazın performansını optimize etmek için 16 KB (ve sonunda daha büyük) sayfa boyutlarını kullanacak. 16 KB sayfa boyutuna sahip cihazlar için destek eklemek, uygulamanızın bu cihazlarda çalışmasını sağlar ve uygulamanızın ilgili performans iyileştirmelerinden yararlanmasına yardımcı olur. Yeniden derlenmeyen uygulamalar, gelecekteki Android sürümlerinde 16 KB'lık cihazlarda çalışmayacaktır.

Uygulamanıza destek eklemenize yardımcı olmak için uygulamanızın etkilenip etkilenmediğini kontrol etme, uygulamanızı yeniden oluşturma (geçerliyse) ve emülatörleri (Android Emulator için Android 15 sistem görüntüleri dahil) kullanarak uygulamanızı 16 KB ortamında test etme hakkında rehberlik sağladık.

Google Play uyumluluk şartı

Uygulamanızın Android'in en yeni sürümlerinde doğru şekilde çalışmasını sağlamak için Android 15 (API düzeyi 35) ve sonraki sürümleri hedefleyen tüm uygulamaların Google Play'deki 64 bit cihazlarda 16 KB'lık bellek sayfası boyutlarını desteklemesi gerekir. 1 Şubat 2027'den itibaren, uygulama güncellemeleriniz 16 KB'lık bellek sayfası boyutlarını desteklemiyorsa bu güncellemeleri yayınlayamazsınız.

Google Play Console'da, uygulama güncellemelerinin 1 Şubat 2027'ye kadar 16 KB'lık bellek sayfası boyutlarını desteklemesi gerektiğini belirten uyarı
Şekil 1. Google Play Console uyumluluk uyarısı.

Avantajlar ve performans artışları

16 KB sayfa boyutlarıyla yapılandırılan cihazlar, ortalama olarak biraz daha fazla bellek kullanır. Ancak, hem sistem hem de uygulamalar için çeşitli performans iyileştirmeleri sağlar:

  • Sistem bellek baskısı altındayken daha düşük uygulama başlatma süreleri: Test ettiğimiz bazı uygulamalarda daha belirgin iyileştirmeler (%30'a varan) ile birlikte ortalama %3, 16 daha düşük
  • Uygulama başlatma sırasında güç tüketimi azaltıldı: Ortalama% 4,56 oranında azalma
  • Daha hızlı kamera başlatma: Ortalama% 4,48 daha hızlı çalışır durumda başlatma ve ortalama% 6,60 daha hızlı soğuk başlatma
  • İyileştirilmiş sistem önyükleme süresi: Ortalama %8 (yaklaşık 950 milisaniye) iyileşme

Bu iyileştirmeler, ilk testlerimizi temel almaktadır ve gerçek cihazlardaki sonuçlar büyük olasılıkla farklılık gösterecektir. Testlerimizi sürdürürken uygulamaların olası kazanımlara ilişkin ek analizler sağlayacağız.

Uygulamanızın etkilenip etkilenmediğini kontrol etme

Uygulamanız yerel kod kullanıyorsa uygulamanızı 16 KB cihazları destekleyecek şekilde yeniden oluşturmanız gerekir. Uygulamanızın yerel kod kullanıp kullanmadığından emin değilseniz APK Analiz Aracı'nı kullanarak yerel kod olup olmadığını belirleyebilir ve ardından bulduğunuz paylaşılan kitaplıklar için ELF segmentlerinin hizalamasını kontrol edebilirsiniz. Android Studio, hizalama sorunlarını otomatik olarak algılamanıza yardımcı olan özellikler de sunar.

Uygulamanızda yalnızca Java programlama dilinde veya Kotlin'de yazılmış kodlar (tüm kitaplıklar veya SDK'lar dahil) kullanılıyorsa uygulamanız 16 KB cihazları zaten destekliyor demektir. Bununla birlikte, uygulama davranışında beklenmedik bir gerileme olmadığını doğrulamak için uygulamanızı 16 KB ortamında test etmenizi öneririz.

Uygulamanız yerel kod kullanıyor mu?

Aşağıdakilerden herhangi biri geçerliyse uygulamanız yerel kod kullanıyordur:

  • Uygulamanızda C/C++ (yerel) kod kullanılıyorsa. Uygulamanız Android NDK kullanıyorsa yerel kod kullanıyor demektir.
  • Uygulamanız, bunları kullanan üçüncü taraf yerel kitaplıklar veya bağımlılıklarla (ör. SDK'lar) bağlantı kuruyorsa
  • Uygulamanız, cihazda yerel kitaplıklar kullanan bir üçüncü taraf uygulama oluşturucu tarafından oluşturulmuş.

APK Analyzer'ı kullanarak yerel kitaplıkları belirleme

APK Analyzer, derlenmiş bir APK'nın çeşitli yönlerini değerlendirmenize olanak tanıyan bir araçtır. Uygulamanızın yerel kod kullanıp kullanmadığını kontrol etmek için (16 KB ile uyumlu olup olmadığına bakılmaksızın):

  1. Android Studio'yu açın, ardından File > Open'ı (Dosya > Aç) tıklayıp herhangi bir projeyi seçin.
  2. Menü çubuğundan Build > Analyze APK...'yı (Derle > APK'yı analiz et...) tıklayın.

    APK Analyzer'ı başlatmak için Studio Build menü seçeneği
  3. Analiz etmek istediğiniz APK'yı seçin.

  4. Varsa paylaşılan nesne (.so) dosyalarını barındıran lib klasörüne bakın. Paylaşılan nesne dosyaları varsa uygulamanız yerel kod kullanır. Hizalama sütununda, hizalama sorunları olan dosyalar için uyarı mesajları gösterilir. Paylaşılan nesne dosyası veya lib klasörü yoksa uygulamanız yerel kod kullanmıyor demektir.

    Paylaşılan nesne dosyalarının mevcut olduğunu gösteren APK Analyzer görünümü

Otomatik kontrollerle hizalama sorunlarını tespit etme

Önceden derlenmiş kitaplıklarınız veya APK'larınız 16 KB ile uyumlu değilse Android Studio sizi proaktif olarak uyarır. Hangi kitaplıkların güncellenmesi gerektiğini veya kod değişikliği gerekip gerekmediğini incelemek için APK Analyzer aracını kullanın.

Projedeki hizalama sorunlarıyla ilgili Studio uyarı bildirimleri

Android Studio'daki Lint, 16 KB'a uygun olmayan yerel kitaplıkları da vurgular.

Hizalanmamış yerel kitaplık hakkında Studio linter uyarısı

Paylaşılan kitaplıklar için ELF segmentlerinin hizalamasını kontrol etme

Paylaşılan kitaplıkların ELF segmentlerinin 16 KB ELF hizalaması kullanılarak doğru şekilde hizalandığını doğrulayın.

APK Analyzer'ı kullanma (Önerilir)

Paylaşılan kitaplıklarınızın hizalamasını doğrulamanın en kolay yolu Android Studio'da APK Analyzer'ı kullanmaktır. Paylaşılan bir nesne dosyası 16 KB hizalı değilse Hizalama sütununda bir uyarı mesajı gösterilir.

check_elf_alignment.sh komut dosyasını kullanma (Linux veya macOS)

Linux veya macOS'te geliştirme yapıyorsanız ve komut dosyası kullanmayı tercih ediyorsanız check_elf_alignment.sh komut dosyasını kullanabilirsiniz:

  1. check_elf_alignment.sh komut dosyasını bir dosyaya kaydedin.

  2. Komut dosyasını uygulamanızın APK dosyasında çalıştırın:

    check_elf_alignment.sh APK_NAME.apk
    

    Komut dosyası, tüm arm64-v8a paylaşılan kitaplıkları için ALIGNED veya UNALIGNED çıkışı verir.

  3. arm64-v8a veya x86_64 paylaşılan kitaplıkları UNALIGNED ise bu kitaplıkların paketlemesini güncellemeniz, ardından uygulamanızı yeniden derlemeniz ve bu bölümdeki adımları uygulayarak yeniden test etmeniz gerekir.

Komut satırı araçlarını doğrudan kullanma

ELF segmentlerinin hizalamasını doğrudan komut satırı araçlarını kullanarak kontrol etmek için aşağıdaki adımları uygulayın:

  1. Android SDK Build-Tools'un 35.0.0 veya sonraki bir sürümünün ve Android NDK'nin, Android Studio'daki SDK Manager veya sdkmanager komut satırı aracı kullanılarak yüklendiğinden emin olun.
  2. Uygulamanızın APK dosyasını ayıklayın:

    Linux veya macOS

    unzip APK_NAME.apk -d /tmp/my_apk_out
    

    Windows (PowerShell)

    Expand-Archive -Path .\APK_NAME.apk -DestinationPath ~\tmp\my_apk_out
    
  3. APK dosyanızı çıkardığınız geçici dizinde, paylaşılan nesne (.so) dosyaları için lib dizininin içeriğini kontrol edin. Bunlar, APK Analyzer'ı kullanarak yerel kitaplıkları tanımlarken gördüğünüz paylaşılan nesne dosyalarıyla aynıdır. Her paylaşılan nesne dosyasında aşağıdaki komutu çalıştırın:

    Linux veya macOS

    SDK_ROOT_LOCATION/Android/sdk/ndk/NDK_VERSION/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump -p SHARED_OBJECT_FILE.so | grep LOAD
    

    Windows (PowerShell)

    SDK_ROOT_LOCATION\Android\sdk\ndk\NDK_VERSION\toolchains\llvm\prebuilt\windows-x86_64\bin\llvm-objdump.exe -p SHARED_OBJECT_FILE.so | Select-String -Pattern "LOAD"
    

    Burada SDK_ROOT_LOCATION, Android SDK'yı yüklediğiniz dizinin yolu, SHARED_OBJECT_FILE, kontrol ettiğiniz paylaşılan nesne dosyasının adı ve NDK_VERSION, yüklediğiniz Android NDK'nın sürümüdür (örneğin, 28.0.12433566). Kontrol ettiğiniz her dosya için çıkış aşağıdakine benzer:

    LOAD off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**14
    LOAD off    0x0000000000042a90 vaddr 0x0000000000043a90 paddr 0x0000000000043a90 align 2**14
    LOAD off    0x0000000000046230 vaddr 0x0000000000048230 paddr 0x0000000000048230 align 2**14
    
  4. Yük segmentlerinin 2**14 değerinden küçük değerlere sahip olmadığından emin olmak için çıkış satırlarını kontrol edin. Yükleme segmentlerinden herhangi biri 2**13, 2**12 veya daha düşük değerlere sahipse bu kitaplıkların paketlemesini güncellemeniz, ardından uygulamanızı yeniden derlemeniz ve bu bölümdeki adımları uygulayarak yeniden test etmeniz gerekir.

  5. Ardından, uygulamanızın APK dosyasında zipalign komut satırı aracını çalıştırın:

    Linux veya macOS

    SDK_ROOT_LOCATION/Android/sdk/build-tools/35.0.0/zipalign -v -c -P 16 4 APK_NAME.apk
    

    Windows (PowerShell)

    SDK_ROOT_LOCATION\Android\sdk\build-tools\35.0.0\zipalign.exe -v -c -P 16 4 APK_NAME.apk
    

    Burada SDK_ROOT_LOCATION, Android SDK'yı yüklediğiniz dizinin yolu, APK_NAME ise uygulamanızın APK dosyasının adıdır. Tüm paylaşılan kitaplıklar doğru şekilde hizalanmışsa çıkışın son satırında "Doğrulama başarılı" ifadesi yer alır.

    Doğrulama başarısız olduysa bazı paylaşılan kitaplıkların yeniden hizalanması gerekir. Bu nedenle, bu kitaplıkların paketlemesini güncellemeniz, ardından uygulamanızı yeniden derlemeniz ve bu bölümdeki adımları uygulayarak yeniden test etmeniz gerekir.

RELRO güvenlik işaretini kontrol etme

Modern bağlayıcılar, güvenlik açıklarını azaltmak için Yeniden Konumlandırma Salt Okunur (RELRO) işaretini kullanarak paylaşılan nesne dosyasının yeniden konumlandırma hedef bölümlerini (ör. .got ve .data.rel.ro) dinamik yeniden konumlandırmalar tamamlandıktan sonra salt okunur hale getirir. Derlemenizde RELRO işaretini etkinleştirin.

GNU_RELRO, sonraki yazılabilir verilerle (.data veya .bss gibi) yazılabilir bir LOAD segmenti paylaştığında GNU_RELRO segmentinin bitiş adresi (VirtAddr + MemSiz) 16 KB hizalı (0x4000) olmalıdır. Aksi takdirde, Android Bağlayıcı GNU_RELRO'nin sonunu içeren 16 KB'lık sayfayı salt okunur olarak işaretlediğinde, aynı 16 KB'lık sayfanın geri kalanında bulunan bitişik yazılabilir veriler de salt okunur hale gelir ve bu verilere yazıldığında uygulama çalışma zamanında segmentasyon hatası (SIGSEGV) ile kilitlenir. Bu durum genellikle .so dosyası, ilgili işaretler etkinleştirilmeden NDK araç zinciri r27 ve daha eski sürümlerle oluşturulduğunda ortaya çıkar.

Paylaşılan nesne dosyalarınızın RELRO uyumluluk durumunu doğrudan kontrol etmek için Android Studio'daki APK Analyzer'ı kullanabilirsiniz.

Android Studio'daki APK Analyzer, yerel kitaplıklar için RELRO uyumluluğunu gösteriyor.

Komut satırı araçlarını kullanma

Hizalamayı manuel olarak kontrol etmeyi tercih ediyorsanız veya süreci otomatikleştirmeniz gerekiyorsa aşağıdaki adımları uygulayın:

1. adım: Program başlıklarını inceleyin

Her paylaşılan nesne dosyasında aşağıdaki komutu çalıştırın (Linux'ta darwin-x86_64 yerine linux-x86_64 yazın):

Linux veya macOS

SDK_ROOT_LOCATION/Android/sdk/ndk/NDK_VERSION/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf -Wl SHARED_OBJECT_FILE.so | grep 'LOAD\|RELRO\|Type'

Windows (PowerShell)

SDK_ROOT_LOCATION\Android\sdk\ndk\NDK_VERSION\toolchains\llvm\prebuilt\windows-x86_64\bin\llvm-readelf.exe -Wl SHARED_OBJECT_FILE.so | Select-String -Pattern 'LOAD|RELRO|Type'

RELRO segmenti varsa GNU_RELRO dizesi yazdırılır.

2. adım: RELRO için 16 KB uyumluluğunu doğrulayın

Aşağıdaki koşullardan herhangi biri karşılanıyorsa paylaşılan nesne dosyası RELRO açısından 16 KB ile uyumludur:

  1. Program başlıklarında GNU_RELRO segmenti yok.
  2. GNU_RELRO bitiş adresi 16 KB hizalıdır: Sanal adresinin (VirtAddr) ve bellek boyutunun (MemSiz) toplamı 16 KB'a (0x4000) bölündüğünde sıfır kalanını (modulo) verir: (VirtAddr + MemSiz) % 0x4000 == 0.
  3. Aynı LOAD segmentinde GNU_RELRO öğesinden sonra yazılabilir veri yok: GNU_RELRO, içinde bulunduğu LOAD segmentinin geri kalanının tamamını kaplar (yani LOAD.VirtAddr + LOAD.MemSiz == RELRO.VirtAddr + RELRO.MemSiz). Bu nedenle, yazılabilir .data veya .bss bölümleri sondaki sayfayı paylaşmaz.

Örnekler

Aşağıdaki örneklerde, farklı GNU_RELRO yapılandırmaları için llvm-readelf çıkışının nasıl değerlendirileceği gösterilmektedir.

1. örnek: Hizalanmamış .so dosyası (uygun değil)

Bu örnekte GNU_RELRO, sonraki yazılabilir verilerle bir RW LOAD segmentini paylaşıyor ve bitiş adresi 0x4000'ün katı değil:

Type           Offset   VirtAddr           PhysAddr           FileSiz MemSiz  Flg Align
LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x0cfaf0 0x0cfaf0 R E 0x4000
LOAD           0x0cfaf0 0x00000000000dfaf0 0x00000000000dfaf0 0x02510 0x04510 RW  0x4000
GNU_RELRO      0x0cfaf0 0x00000000000dfaf0 0x00000000000dfaf0 0x01510 0x01510 R   0x1
  • Formül: (VirtAddr + MemSiz) % 0x4000 == 0
  • Sonuç: (0xdfaf0 + 0x01510) % 0x4000 = 0xE1000 % 0x4000 == 0x1000

0x1000 sıfır olmadığından ve içeren LOAD segmenti 0xE1000 sonrasında devam ettiğinden (0xdfaf0 + 0x04510 = 0xE4000 adresinde sona erer) bu .so dosyası 16 KB ile uyumlu değildir. 16 KB'lık bir cihazda bağlayıcı, RELRO koruma aralığını 16 KB'lık sayfa sınırlarına yuvarlayarak 0xDC000 (önceki sayfa sonu) ile 0xE4000 arasını salt okunur olarak işaretler. Ancak .so dosyasının yazılabilir .data ve .bss bölümleri 0xE1000 ile 0xE4000 arasındaki alt aralıkta yer aldığından, çalışma zamanında değiştirildiğinde segmentasyon hatası oluşur. Bu .so dosyasını, Uygulamanızı 16 KB ELF hizalaması kullanarak derleme bölümünde açıklandığı şekilde yeniden derleyin.

2. örnek: RELRO segmentiyle hizalanmış .so dosyası (Uyumlu)

Bu örnekte, GNU_RELRO segmentinin sonu 16 KB'lık bir sayfa sınırına denk geliyor:

Type           Offset   VirtAddr           PhysAddr           FileSiz MemSiz  Flg Align
LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x0cfaf0 0x0cfaf0 R E 0x4000
LOAD           0x0cfaf0 0x00000000000dfaf0 0x00000000000dfaf0 0x01510 0x03510 RW  0x4000
GNU_RELRO      0x0cfaf0 0x00000000000dfaf0 0x00000000000dfaf0 0x00510 0x00510 R   0x1
  • Formül: (VirtAddr + MemSiz) % 0x4000 == 0
  • Sonuç: (0xdfaf0 + 0x00510) % 0x4000 = 0xE0000 % 0x4000 == 0

Kalan 0 olduğu için RELRO koruması 0xE0000 sayfa sınırında düzgün bir şekilde sona erer ve 0xE0000 adresinden başlayan yazılabilir veriler etkilenmez.

3. örnek: RELRO segmenti olmayan .so dosyası (Uyumlu)
Type           Offset   VirtAddr           PhysAddr           FileSiz MemSiz  Flg Align
LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x000680 0x000680 R E 0x4000
LOAD           0x000680 0x0000000000004680 0x0000000000004680 0x0001d8 0x0001d8 RW  0x4000

Bu .so dosyasında GNU_RELRO segmenti olmadığından RELRO sayfa sınırı sorunları geçerli değildir (ancak güvenlik için RELRO'nun etkinleştirilmesi önerilir).

4. örnek: Kendi LOAD segmentinde GNU_RELRO (uygun)

Bu örnekte GNU_RELRO, 16 KB sınırında bitmiyor ancak aynı LOAD segmentinde yazılabilir veri bulunmadığı için yine de uyumludur:

Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x000680 0x000680 R E 0x4000
LOAD           0x000680 0x0000000000004680 0x0000000000004680 0x0001d8 0x000980 RW  0x4000
GNU_RELRO      0x000680 0x0000000000004680 0x0000000000004680 0x0001d8 0x000980 R   0x1
  • Formül: (VirtAddr + MemSiz) % 0x4000 == 0
  • Sonuç: (0x4680 + 0x0980) % 0x4000 = 0x5000 % 0x4000 == 0x1000

0x1000 sıfır olmasa da bu .so dosyası 16 KB ile uyumludur. GNU_RELRO ile onu içeren LOAD segmenti (ikinci LOAD girişi) karşılaştırıldığında, her ikisinin de VirtAddr 0x4680 adresinde başladığı ve tam olarak aynı adreste (0x4680 + 0x0980 = 0x5000) bittiği görülür.

LOAD segmentinin tamamı yalnızca RELRO verileri içerdiğinden 0x5000 ile 0x8000 arasındaki alt aralıkta yazılabilir .data veya .bss verisi yoktur (kitaplıkta RELRO olmayan yazılabilir veri yoktur veya sonraki yazılabilir LOAD segmenti 0x8000 ya da daha ilerideki ayrı bir 16 KB sayfa sınırında başlar). Bağlayıcının salt okunur koruması, yazılabilir verilerle çakışmaz. Bu nedenle segmentasyon hatası oluşmaz.

Uygulamanızı 16 KB cihazları destekleyecek şekilde derleme

Uygulamanız yerel kod kullanıyorsa uygulamanızın 16 KB cihazları desteklediğinden emin olmak için aşağıdaki bölümlerde açıklanan adımları tamamlayın:

  1. Paylaşılan kitaplıklarınızın paketlemesini güncelleme
  2. Uygulamanızı 16 KB ELF hizalaması kullanarak derleme
  3. Kodu düzeltme ve çalışma zamanı sorunlarını çözme
  4. Özel bellek ayırıcıları optimize etme (varsa)
  5. SDK'ların 16 KB desteğini kontrol etme

Paylaşılan kitaplıklarınızın paketlemesini güncelleme

AGP 8.5.1 veya daha yeni bir sürüme yükseltin ve sıkıştırılmamış paylaşılan kitaplıkları kullanın.

ZIP hizalamasını doğrulamak için bundletool aracını kullanın.

Paketinizin hizalamasını görmek için şunları kullanın:

bundletool dump config --bundle=<my .aab>  | grep alignment

PAGE_ALIGNMENT_16K ifadesini görüyorsanız paketiniz 16 KB ZIP hizalaması istiyor demektir. PAGE_ALIGNMENT_4K ifadesini görüyorsanız bu, bu AAB'den oluşturulan APK'nın, ZIP dosyasında 4 KB hizalanmış .so dosyaları içermesini sağlar.

AGP 8.5.1 veya sonraki sürümler

16 KB cihazlar, sıkıştırılmamış paylaşılan kitaplıklarla birlikte gelen uygulamaların 16 KB zip ile uyumlu bir sınırda hizalanmasını gerektirir. Bunun için Android Gradle eklentisi (AGP) 8.5.1 veya sonraki bir sürüme yükseltmeniz gerekir. Yükseltme işlemiyle ilgili ayrıntılar için Android Gradle eklentisi Yükseltme Asistanı bölümüne bakın.

AGP sürümü 8.5 veya daha eski

AGP'yi 8.5.1 veya sonraki bir sürüme yükseltemiyorsanız alternatif olarak sıkıştırılmış paylaşılan kitaplıkları kullanmaya geçebilirsiniz. Uygulamanızı paketlerken Gradle'ın paylaşılan kitaplıklarınızı sıkıştırması için Gradle yapılandırmanızı güncelleyin. Böylece, hizalanmamış paylaşılan kitaplıklarla ilgili uygulama yükleme sorunlarını önleyebilirsiniz.

Modern

build.gradle dosyanıza aşağıdaki seçeneği ekleyin:

android {
  ...
  packagingOptions {
      jniLibs {
        useLegacyPackaging true
      }
  }
}

Kotlin

build.gradle.kts dosyanıza aşağıdaki seçeneği ekleyin:

android {
  ...
  packagingOptions {
      jniLibs {
        useLegacyPackaging = true
      }
  }
}
AGP 8.0 veya daha eski sürümler

8.0 veya daha eski bir AGP sürümü kullanıyorsanız gradle.properties dosyanızda uygulama paketleri için sıkıştırılmamış yerel kitaplık seçeneğini de devre dışı bırakmanız gerekir:

android.bundle.enableUncompressedNativeLibs=false

Uygulamanızı 16 KB ELF hizalaması kullanarak derleme

16 KB cihazlarda uygulamanızın çalışması için paylaşılan kitaplıkların ELF segmentlerinin 16 KB ELF hizalaması kullanılarak doğru şekilde hizalanması gerekir.

Oyun geliştiricileri için: Oyununuz Unity oyun motoru üzerinde çalışıyorsa Unity kılavuzuna bakın. Oyununuz Unreal oyun motoru üzerinde çalışıyorsa Unreal kılavuzuna bakın. Yerel oyun motorları için bu kılavuzu kullanmaya devam edin.

Uygulamanızı 16 KB ELF hizalaması kullanarak derlemek için kullandığınız Android NDK sürümüne bağlı olarak aşağıdaki bölümlerden birindeki adımları tamamlayın.

Android NDK r28 ve sonraki sürümler

NDK sürüm r28 ve sonraki sürümler, varsayılan olarak 16 KB ile uyumlu olacak şekilde derlenir.

Android NDK r27 ve önceki sürümler

Android NDK r27 veya daha eski sürümlerle 16 KB uyumlu paylaşılan kitaplıkların derlenmesini desteklemek için aşağıdaki bağlayıcı işaretlerini kullanın:

-Wl,-z,max-page-size=16384
-Wl,-z,common-page-size=16384

Derleme sistemi yapılandırma dosyalarınızı şu şekilde güncelleyebilirsiniz:

ndk-build

ndk-build kullanıyorsanız 16 KB ELF hizalamasını etkinleştirmek için Android.mk dosyanızı güncelleyin:

LOCAL_LDFLAGS += -Wl,-z,max-page-size=16384 -Wl,-z,common-page-size=16384

CMake

CMake kullanıyorsanız 16 KB ELF hizalamasını etkinleştirmek için CMakeLists.txt dosyanızı güncelleyin.

target_link_options(${CMAKE_PROJECT_NAME} PRIVATE
    "-Wl,-z,max-page-size=16384"
    "-Wl,-z,common-page-size=16384"
)

Kodu düzeltme ve çalışma zamanı sorunlarını çözme

Uygulamanız 16 KB uyumlu olsa bile kodunuzda bir cihazın belirli bir sayfa boyutu kullandığı varsayılıyorsa uygulamanız hatalarla karşılaşabilir. Bunu önlemek için aşağıdaki adımları uygulayın:

  1. PAGE_SIZE sabitine referans veren tüm sabit kodlu bağımlılıkları veya kod mantığınızda bir cihazın sayfa boyutunun 4 KB (4096) olduğunu varsayan örnekleri kaldırın.

    Bunun yerine getpagesize() veya sysconf(_SC_PAGESIZE) kullanın.

  2. mmap() ve sayfa hizalı bağımsız değişkenler gerektiren diğer API'lerin kullanımlarını bulun ve gerektiğinde alternatiflerle değiştirin.

Bazı durumlarda, uygulamanız temel sayfa boyutuna bağlı olmayan uygun bir değer olarak PAGE_SIZE kullanıyorsa bu durum, uygulamanızın 16 KB modunda kullanıldığında bozulmasına neden olmaz. Ancak bu değer, mmap olmadan MAP_FIXED ile çekirdeğe iletilirse çekirdek yine de tam bir sayfa kullanır ve bu da bir miktar bellek israfına neden olur. Bu nedenle, NDK r27 ve sonraki sürümlerde 16 KB modu etkinleştirildiğinde PAGE_SIZE tanımlanmaz.

Uygulamanız PAGE_SIZE değişkenini bu şekilde kullanıyor ve bu değeri hiçbir zaman doğrudan çekirdeğe iletmiyorsa PAGE_SIZE değişkenini kullanmak yerine, başka amaçlarla kullanıldığını ve gerçek bir bellek sayfasını yansıtmadığını belirten yeni bir ada sahip yeni bir değişken oluşturun.

Özel bellek ayırıcıları optimize etme

16 KB sistemlerde, işletim sisteminin tahsis ettiği en küçük fiziksel bellek birimi, 4 KB sistemlere göre dört kat daha büyüktür. Özel bir ayırıcı 4 KB'lık varsayımlara göre tasarlandıysa küçük nesneleri birden fazla 16 KB'lık sayfaya dağıtabilir ve boş belleği gereksiz yere tutabilir. Bu durum, fiziksel bellek kullanımını (RSS) önemli ölçüde artırabilir ve sıkıştırılmış takas (ZRAM) verimliliğini düşürebilir.

Kodunuz kendi bellek havuzlarını yönetiyorsa aşağıdaki önerileri uygulayın:

1. Bellekte yer açmak için sabit kodlu bayt eşikleri kullanmaktan kaçının.

Birçok ayırıcı, madvise(MADV_DONTNEED) kullanarak belleği işletim sistemine ne zaman geri vereceğine karar vermek için sabit bayt sınırları kullanır (ör. yalnızca etkin nesneler 8 KB'tan az yer kaplıyorsa belleği serbest bırak).

16 KB'lık bir sistemde, 16 baytlık tek bir canlı nesne bile 16 KB'lık bir sayfanın tamamını (8 KB'tan büyük) sabitler. Sonuç olarak, serbest bırakma eşiğine hiçbir zaman ulaşılmaz ve ayırıcı, çevredeki kullanılmayan belleği hiçbir zaman çekirdeğe döndürmez.

Yapılması gerekenler: Sayfa yayınlama buluşsal yöntemleri için hiçbir zaman sabit kodlu bayt sabitleri kullanmayın. sysconf(_SC_PAGESIZE) kullanarak çalışma zamanında gerçek sayfa boyutuna göre sürüm eşiklerini dinamik olarak ölçeklendirin.

2. Önce kullanılmış sayfaları doldurma (yoğunluk öncelikli tahsis)

Ayırıcı, belleği ilk giren ilk çıkar (FIFO) veya sırayla dağıtırsa yeni ayırmalar, kısmen doldurulmuş birçok 16 KB'lık sayfaya dağıtılır. Sayfadaki tek bir nesne, 16 KB'ın tamamını fiziksel RAM'de tutar.

Yapılması gerekenler: Boş veya az kullanılan sayfalara dokunmadan önce her zaman en dolu (en yoğun) sayfadan veya bloktan yeni nesneler tahsis edin. Yeni ayırmaları zaten kirli olan sayfalarda yoğunlaştırmak, az kullanılan sayfaların doğal olarak sıfır etkin nesneye boşalmasını sağlar. Böylece 16 KB'lık sayfanın tamamı işletim sistemine bırakılabilir.

3. Bellek havuzlarını 16 KB'a hizalayın ve havuz boyutlarını orta düzeyde tutun.

4 KB sistemler için tasarlanmış çok sayfalı aralıklar, 16 KB çekirdeklerde aşırı miktarda serbest bırakılmamış bellek boşluğu barındırabilir. Ayrıca, 16 KB'a eşit olarak bölünmeyen boyut sınıfları, her sayfanın sonunda parçalanmaya neden olur.

Yapılması gerekenler:

  • Tüm bellek havuzlarının, slab sınırlarının ve arabellek hizalamalarının, çalışma zamanı sayfa boyutunun tam katları olduğundan emin olun.
  • Boşta kalan belleği kaplayan aşırı büyük slab'lerin tahsis edilmesini önlemek için küçük nesne sınıflarının çok sayfalı span boyutlarını yeniden değerlendirin.

4. Önbelleğe alınmış büyük arabellekler için fiziksel belleği hemen serbest bırakma

Özel ayırıcılar, mmap veya munmap sistem çağrılarının ek yükünü ödemeden yeniden kullanılabilmeleri için genellikle büyük arabellekleri (> 64 KB) bellek içi havuzda önbelleğe alır. Ancak bu kirli arabellekleri bellekte tutmak, çıkarma zamanlayıcısını beklerken megabaytlarca fiziksel RAM'i boşa harcar.

Yapılması gerekenler: Sanal bellek adres aralığını hızlı yeniden kullanım için ayrılmış olarak tutun ancak bir arabelleği önbelleğe döndürürken hemen madvise(..., MADV_DONTNEED) veya madvise(..., MADV_FREE) işlevini çağırın. İşletim sistemi, fiziksel RAM'i hemen geri alır. Uygulamanız ise sanal adresi yeniden tahsis etmeden anında tekrar kullanabilir.

5. ZRAM sıkıştırması için tahsisat yerine boşaltma sırasında belleği sıfırlama

Android, arka plan uygulamalarını bellekte tutmak için sıkıştırılmış takas (ZRAM) kullanır. 16 KB'lık cihazlarda, bir sayfada tek bir canlı nesne bile varsa 16 KB'lık sayfanın tamamı yerleşik olarak kalır veya ZRAM'e taşınır. Sayfanın daha önce boşaltılmış kısımlarında kalan çöp veriler (ör. eski işaretçiler ve dizeler) iyi sıkıştırılamaz.

Ayırıcınız belleği sıfırlıyorsa (ör. güvenlik veya sıfır başlatılmış ayırmalar için) ayırma sırasında değil, ayırmayı kaldırma (free()) sırasında sıfırlamayı düşünün:

  • Sabitlenmiş sayfaların maliyeti daha düşüktür: Kısmen dolu 16 KB'lık sayfalardaki boş bellek, ZRAM'de neredeyse sıfıra kadar sıkıştırılır. Bu nedenle, sabitlenmiş sayfalar fiziksel takas alanını boşa harcamaz.
  • Minimum önbellek ek yükü: free() çağrıldığında bellek CPU önbelleğinde zaten sıcaktır. Bu sayede, daha sonra önbellekte yok hatası alınmaz.

Önerilerin özeti

Alan Öneri Beklenen etki
Temizleme eşikleri sysconf(_SC_PAGESIZE) kullanarak sürüm eşiklerini dinamik olarak ölçeklendirin. Sürüm mantığının kalıcı olarak kilitlenmesini önler.
Tahsis sırası Öncelikle en yoğun (neredeyse dolu) sayfadan veya bloktan tahsis edin. Etkin nesneleri bir araya getirerek yerleşik belleği (RSS) azaltır.
Aralık boyutlandırma Boyut sınıflarını 16 KB'lık katlara hizalayın ve aşırı büyük slab'lerden kaçının. Kuyruk sayfası parçalanmasını ortadan kaldırır ve bellek boşluğunu azaltır.
Arabellek önbellekleri Büyük arabellekleri önbelleğe alırken hemen madvise(MADV_DONTNEED) yöntemini çağırın. Hızlı sanal yeniden kullanımı korurken boşta kalan RAM şişmesini ortadan kaldırır.
Takas/ZRAM Belleği tahsisat sırasında değil, free() sırasında sıfırlayın. ZRAM sıkıştırma oranlarını iyileştirerek sabitlenmiş sayfaların maliyetini azaltır.

SDK'ların 16 KB desteğini kontrol etme

Birçok SDK, özellikle kendiniz oluşturursanız veya son önceden derlenmiş sürümleri kullanırsanız 16 KB sayfa boyutlarıyla uyumludur. Ancak bazı önceden derlenmiş SDK'lar veya SDK sürümleri 16 KB ile uyumlu olmadığından, 16 KB ile hangi sürümün kullanılacağını belirlemek için her SDK sağlayıcının web sitesini kontrol etmeniz gerekir.

Uygulamanızı 16 KB ortamında test edin

Uygulamanızı 16 KB cihazları destekleyecek şekilde derledikten sonra, uygulamanızda herhangi bir gerileme olup olmadığını görmek için uygulamanızı 16 KB ortamında test etmeniz gerekir. Bunu yapmak için aşağıdaki adımları uygulayın:

  1. Android 15 SDK veya sonraki bir sürümü ayarlayın.

  2. Aşağıdaki test ortamlarından birini oluşturun:

  3. Test cihazınızı başlatın, ardından 16 KB'lık bir ortam kullandığını doğrulamak için aşağıdaki komutu çalıştırın:

    adb shell getconf PAGE_SIZE
    

    Komut, 16384 değerini döndürmelidir.

  4. Uygulamanızın 16 KB uyumlu olduğunu doğrulamak için aşağıdaki zipalign komutunu çalıştırın. APK_NAME, uygulamanızın APK dosyasının adıdır:

    zipalign -c -P 16 -v 4 APK_NAME.apk
    
  5. Belirli sayfa boyutlarına referans veren kod örneklerini değiştirerek etkilenebilecek alanlara odaklanıp uygulamanızı kapsamlı bir şekilde test edin.

Android Emulator'ı 16 KB tabanlı sistem görüntüsüyle ayarlama

Android Emulator'ı kullanarak 16 KB'lık bir ortam oluşturmak için aşağıdaki adımları uygulayın:

  1. Android Studio'da Tools > SDK Manager'ı (Araçlar > SDK Manager) tıklayın.
  2. SDK Platforms (SDK Platformları) sekmesinde Show Package Details'ı (Paket Ayrıntılarını Göster) seçin, ardından Android VanillaIceCream veya daha yeni bir sürüm bölümünü genişletin ve oluşturmak istediğiniz sanal cihazlara bağlı olarak aşağıdaki emülatör sistem görüntülerinden birini veya her ikisini seçin:

    • Google API'leri Deneysel 16 KB Sayfa Boyutu ARM 64 v8a Sistem Resmi
    • Google API'leri Deneysel 16 KB Sayfa Boyutu Intel x86_64 Atom Sistem Görüntüsü
    Android Studio'daki SDK Manager'ı kullanarak 16 KB emülatör sistem görüntülerini indirme
  3. Seçtiğiniz sistem görüntülerini indirmek için Apply > OK'i (Uygula > Tamam) tıklayın.

  4. Android 15 için sanal cihaz oluşturma adımlarını uygulayın ve sistem görüntüsü seçmeniz istendiğinde indirdiğiniz 16 KB sistem görüntüsünü seçin. Otomatik olarak önerilmezse 16 KB sistem görüntüsünü Diğer Görüntüler sekmesinde bulabilirsiniz.

    Diğer Resimler sekmesinde 16 KB emülatör görüntüsünü bulun.

Emülatörü başlatma

Android Emulator'ı ve sanal cihazları ayarlamayı tamamladıktan sonra emülatörü hedef cihaz menüsünden veya komut satırından başlatın.

Geliştirici seçeneklerini kullanarak bir cihazda 16 KB modunu etkinleştirme

Cihazı 16 KB modunda başlatmak için 16 KB sayfa boyutuyla başlat geliştirici seçeneğini etkinleştirin.

Android 15'in QPR sürümlerinde, cihazı 16 KB modunda başlatmak ve cihaz üzerinde test yapmak için belirli cihazlarda bulunan geliştirici seçeneğini kullanabilirsiniz. Geliştirici seçeneğini kullanmadan önce Ayarlar > Sistem > Yazılım güncellemeleri'ne gidip varsa güncellemeleri uygulayın.

Bu geliştirici seçeneği aşağıdaki cihazlarda kullanılabilir:

  • Pixel 8 ve 8 Pro (Android 15 QPR1 veya sonraki sürümlerle)

  • Pixel 8a (Android 15 QPR1 veya sonraki sürümler)

  • Pixel 9, 9 Pro ve 9 Pro XL (Android 15 QPR2 veya sonraki bir sürüm yüklü)

  • Pixel 9a (Android 16 veya sonraki sürümler)

16 KB geriye dönük uyumluluk modu

Sayfa boyutu uyumluluk modunda uyarı

Sayfa boyutu uyumluluk modunda uyarı

16 KB geriye dönük uyumluluk seçeneği, cihaz 16 KB çekirdek çalıştırırken kullanılabilir. Paket yöneticisi, aşağıdaki koşullar karşılandığında uygulamayı 16 KB geriye dönük uyumluluk modunda çalıştırır:

  • Uygulamada, LOAD segment hizalaması 4 KB olan ELF dosyaları (.so uzantılı) varsa
  • Sıkıştırılmış APK'da 4 KB ZIP uyumlu, sıkıştırılmamış ELF dosyaları varsa

Paket yöneticisi bir uygulama için 16 KB geriye dönük uyumluluk modunu etkinleştirdiyse uygulama ilk başlatıldığında 16 KB geriye dönük uyumluluk modunda çalıştığını belirten bir uyarı gösterir.

16 KB geriye dönük uyumluluk modu bazı uygulamaların çalışmasına olanak tanır ancak en iyi güvenilirlik ve kararlılık için uygulamaların yine de 16 KB ile uyumlu olması gerekir.

Uygulama bilgileri sayfasındaki Gelişmiş bölümünde, belirli bir uygulama için 16 KB geriye dönük uyumluluk modunu etkinleştirmek veya devre dışı bırakmak üzere Uygulamayı sayfa boyutu uyumluluk moduyla çalıştır ayarını açın ya da kapatın. Bu ayar yalnızca cihaz 16 KB sayfa boyutuyla çalışırken görünür.

Sayfa boyutu uyumluluk modu ayarı

Sayfa boyutu uyumluluk modu ayarı

Cihazdaki her uygulama için 16 KB geriye dönük uyumluluğu zorunlu kılmak istiyorsanız:

adb shell setprop bionic.linker.16kb.app_compat.enabled true
adb shell setprop pm.16kb.app_compat.disabled false

Cihazdaki her uygulama için 16 KB geriye dönük uyumluluğu zorunlu olarak devre dışı bırakmak istiyorsanız:

adb shell setprop bionic.linker.16kb.app_compat.enabled false
adb shell setprop pm.16kb.app_compat.disabled true

Android 17'de, her uygulama için 16 KB geriye dönük uyumluluğu zorunlu olarak devre dışı bırakabilir ve uyumsuz ikili dosyaların hemen iptal edilmesine neden olabilirsiniz:

    adb shell setprop bionic.linker.16kb.app_compat.enabled fatal
    adb shell setprop pm.16kb.app_compat.disabled true

Belirli bir uygulamanın AndroidManifest.xml dosyasında geriye dönük uyumluluk modunu etkinleştirmek veya devre dışı bırakmak için android:pageSizeCompat özelliğini etkin ya da devre dışı olarak ayarlayın. Bu özellik ayarlandığında uygulama, başlatılırken geriye dönük uyumluluk modu uyarıları göstermez.