Berita Produk

Mengonfigurasi dan Memecahkan Masalah Aturan Keep R8

7 menit membaca

Dalam pengembangan Android modern, pengiriman aplikasi kecil, cepat, dan aman adalah ekspektasi pengguna yang mendasar. Alat utama sistem build Android untuk mencapai hal ini adalah pengoptimal R8 , compiler yang menangani penghapusan kode dan resource yang tidak digunakan untuk penyingkatan, penggantian nama atau minifikasi kode, dan pengoptimalan aplikasi.

Mengaktifkan R8 adalah langkah penting dalam menyiapkan aplikasi untuk rilis, tetapi developer harus memberikan panduan dalam bentuk "Aturan Keep".

Setelah membaca artikel ini, tonton video Minggu Sorotan Performa di YouTube tentang cara mengaktifkan, men-debug, dan memecahkan masalah pengoptimal R8.

 

 

Alasan Aturan Keep diperlukan

Kebutuhan untuk menulis Aturan Keep berasal dari konflik inti: R8 adalah alat analisis statis, tetapi aplikasi Android sering mengandalkan pola eksekusi dinamis seperti refleksi atau panggilan masuk dan keluar dari kode native menggunakan JNI (Java Native Interface).

R8 membuat grafik kode yang digunakan dengan menganalisis panggilan langsung. Saat kode diakses secara dinamis, analisis statis R8 tidak dapat memprediksi hal tersebut dan akan mengidentifikasi kode tersebut sebagai tidak digunakan dan menghapusnya, sehingga menyebabkan error runtime.

Aturan keep adalah petunjuk eksplisit ke compiler R8, yang menyatakan: "Class, metode, atau kolom tertentu ini adalah titik entri yang akan diakses secara dinamis saat runtime. Anda harus mempertahankannya, meskipun Anda tidak dapat menemukan referensi langsung ke dalamnya."

Lihat panduan resmi untuk mengetahui detail selengkapnya tentang Aturan Keep.

Tempat menulis Aturan Keep

Aturan Keep Kustom untuk aplikasi ditulis dalam file teks. Menurut konvensi, file ini diberi nama proguard-rules.pro dan terletak di root aplikasi atau modul library. File ini kemudian ditentukan dalam jenis build release file build.gradle.kts modul Anda.

release {

    isShrinkResources = true

    isMinifyEnabled = true

    proguardFiles(

        getDefaultProguardFile("proguard-android-optimize.txt"),

        "proguard-rules.pro",

    )

}

Menggunakan file default yang benar

Metode getDefaultProguardFile mengimpor kumpulan aturan default yang disediakan oleh Android SDK. Jika menggunakan file yang salah, aplikasi Anda mungkin tidak dioptimalkan. Pastikan untuk menggunakan proguard-android-optimize.txt. File ini menyediakan Aturan Keep default untuk komponen Android standar dan mengaktifkan pengoptimalan kode R8. proguard-android.txt yang sudah tidak berlaku hanya menyediakan Aturan Keep, tetapi tidak mengaktifkan pengoptimalan R8.

progaurd.png

Karena ini adalah masalah performa yang serius, kami mulai memperingatkan developer tentang penggunaan file yang salah, mulai dari Android Studio Narwhal 3 Feature Drop.Dan mulai dari Plugin Android Gradle Versi 9.0, kami tidak lagi mendukung file proguard-android.txt yang sudah tidak berlaku. Jadi, pastikan Anda mengupgrade ke versi yang dioptimalkan.

Cara menulis Aturan Keep

Aturan keep terdiri dari tiga bagian utama:

  1. Opsi seperti -keep atau -keepclassmembers
  2. Pengubah opsional seperti allowshrinking
  3. Spesifikasi class yang menentukan kode yang akan dicocokkan

Untuk sintaksis dan contoh lengkap, lihat panduan untuk menambahkan Aturan Keep.

Anti-pola Aturan Keep

Penting untuk mengetahui praktik terbaik, tetapi juga anti-pola. Anti-pola ini sering kali muncul dari kesalahpahaman atau pintasan pemecahan masalah dan dapat menjadi bencana bagi performa build produksi.

Opsi global

Flag ini adalah tombol global yang tidak boleh digunakan dalam build rilis. Flag ini hanya untuk proses debug sementara guna mengisolasi masalah.

Penggunaan -dontotptimize secara efektif menonaktifkan pengoptimalan performa R8 yang menyebabkan aplikasi menjadi lebih lambat.

Saat menggunakan -dontobfuscate, Anda menonaktifkan semua penggantian nama dan menggunakan -dontshrink akan menonaktifkan penghapusan kode yang tidak digunakan. Kedua aturan global ini meningkatkan ukuran aplikasi.

Hindari penggunaan flag global ini di lingkungan produksi jika memungkinkan untuk pengalaman pengguna aplikasi yang lebih berperforma.

Aturan keep yang terlalu luas

Cara termudah untuk membatalkan manfaat R8 adalah dengan menulis Aturan Keep yang terlalu luas. Aturan keep seperti di bawah ini menginstruksikan pengoptimal R8 untuk tidak menyusutkan, tidak meng-obfuscate, dan tidak mengoptimalkan class apa pun dalam paket ini atau sub-paket apa pun. Tindakan ini sepenuhnya menghapus manfaat R8 untuk seluruh paket tersebut. Coba tulis Aturan Keep yang sempit dan spesifik.

-keep class com.example.package.** { *;} // WIDE KEEP RULES CAUSE PROBLEMS

Operator inversi (!)

Operator inversi (!) tampaknya merupakan cara yang efektif untuk mengecualikan paket dari aturan. Namun, hal ini tidak sesederhana itu. Lihat contoh berikut.

-keep class !com.example.my_package.** { *; } // USE WITH CAUTION

Anda mungkin berpikir bahwa aturan ini berarti "jangan pertahankan class dicom.example.package." Namun, sebenarnya aturan ini berarti "pertahankan setiap class, metode, dan properti di seluruh aplikasi yang tidak ada di com.example.package." Jika hal ini mengejutkan Anda, sebaiknya periksa negasi apa pun dalam konfigurasi R8 Anda.

Aturan redundan untuk komponen Android

Kesalahan umum lainnya adalah menambahkan Aturan Keep secara manual untuk ActivitiesServices, atau BroadcastReceivers aplikasi Anda. Hal ini tidak diperlukan. File proguard-android-optimize.txt default sudah menyertakan aturan yang relevan agar komponen Android standar ini dapat langsung digunakan.

Selain itu, banyak library yang memiliki Aturan Keep sendiri. Jadi, Anda tidak perlu menulis aturan sendiri untuk hal ini. Jika ada masalah dengan Aturan Keep dari library yang Anda gunakan, sebaiknya hubungi penulis library untuk mengetahui masalahnya.

Praktik terbaik Aturan Keep

Setelah mengetahui hal yang tidak boleh dilakukan, mari kita bahas praktik terbaik.

Menulis Aturan Keep yang sempit

Aturan Keep yang baik harus sesempit dan sespesifik mungkin. Aturan ini hanya boleh mempertahankan hal yang diperlukan, sehingga R8 dapat mengoptimalkan hal lainnya.

AturanKualitas

 

-keep class com.example.** { ; }

 

Rendah: Mempertahankan seluruh paket dan sub-paketnya

 

-keep class com.example.MyClass { ; }

 

Rendah: Mempertahankan seluruh class yang kemungkinan masih terlalu luas
-keepclassmembers class com.example.MyClass {

    private java.lang.String secretMessage;

    public void onNativeEvent(java.lang.String);

}
Tinggi: Hanya metode dan properti yang relevan dari class tertentu yang dipertahankan

Menggunakan ancestor umum

Daripada menulis Aturan Keep terpisah untuk beberapa model data yang berbeda, tulis satu aturan yang menargetkan class atau antarmuka dasar umum. Aturan di bawah ini memberi tahu R8 untuk mempertahankan anggota class yang menerapkan antarmuka ini dan sangat skalabel.

# Keep all fields of any class that implements SerializableModel

-keepclassmembers class * implements com.example.models.SerializableModel {

    <fields>;

}

Menggunakan Anotasi untuk menargetkan beberapa class

Buat anotasi kustom (misalnya, @Serialize) dan gunakan untuk "menandai" class yang kolomnya perlu dipertahankan. Ini adalah pola lain yang bersih, deklaratif, dan sangat skalabel. Anda juga dapat membuat Aturan Keep untuk anotasi yang sudah ada dari framework yang Anda gunakan.

# Keep all fields of any class annotated with @Serialize

-keepclassmembers class * {

    @com.example.annotations.Serialize <fields>;

}

Memilih Opsi Keep yang tepat

Opsi Keep adalah bagian terpenting dari aturan. Memilih opsi yang salah dapat menonaktifkan pengoptimalan tanpa perlu.

Opsi KeepFungsi
-keepMencegah class dan anggota yang disebutkan dalam deklarasi dihapus atau diganti namanya.
-keepclassmembersMencegah anggota yang ditentukan dihapus atau diganti namanya, tetapi memungkinkan class itu sendiri dihapus, tetapi hanya pada class yang tidak dihapus.
-keepclasseswithmembersKombinasi: Mempertahankan class dan anggotanya, hanya jika semua anggota yang ditentukan ada.

Anda dapat menemukan informasi selengkapnya tentang opsi keep di dokumentasi kami untuk Opsi Keep.

Mengizinkan pengoptimalan dengan Pengubah

Pengubah seperti allowshrinking dan allowobfuscation melonggarkan aturan -keep yang luas, sehingga memberikan kembali kemampuan pengoptimalan ke R8. Misalnya, jika library lama mengharuskan Anda menggunakan -keep pada seluruh class, Anda mungkin dapat mengklaim kembali beberapa pengoptimalan dengan mengizinkan penyingkatan dan obfuscation:

# Keep this class, but allow R8 to remove it if it's unused and allow R8 to rename it.

-keep,allowshrinking,allowobfuscation class com.example.LegacyClass

Menambahkan opsi global untuk pengoptimalan tambahan

Selain Aturan Keep, Anda dapat menambahkan flag global ke file konfigurasi R8 untuk mendorong pengoptimalan yang lebih banyak.

-repackageclasses adalah opsi yang efektif yang menginstruksikan R8 untuk memindahkan semua class yang di-obfuscate ke dalam satu paket. Hal ini menghemat ruang yang signifikan dalam file DEX dengan menghapus string nama paket yang redundan.

-allowaccessmodification memungkinkan R8 memperluas akses (misalnya, private ke public) untuk mengaktifkan inlining yang lebih agresif. Opsi ini kini diaktifkan secara default saat menggunakan proguard-android-optimize.txt.

Peringatan: Penulis library tidak boleh menambahkan flag pengoptimalan global ini ke aturan konsumen mereka, karena akan diterapkan secara paksa ke seluruh aplikasi.

Untuk lebih jelasnya, di versi 9.0 Plugin Android Gradle, kami akan mulai mengabaikan flag pengoptimalan global dari library sepenuhnya. 

Praktik terbaik untuk library

Setiap aplikasi Android bergantung pada library dengan satu atau lain cara. Jadi, mari kita bahas praktik terbaik untuk library.

Untuk developer library

Jika library Anda menggunakan refleksi atau JNI, Anda bertanggung jawab untuk menyediakan Aturan Keep yang diperlukan kepada konsumennya. Aturan ini ditempatkan dalam file consumer-rules.pro, yang kemudian otomatis di-bundle di dalam file AAR library.

android {

    defaultConfig {

        consumerProguardFiles("consumer-rules.pro")

    }

    ...

}

Untuk konsumen library

Memfilter Aturan Keep yang bermasalah

Jika Anda harus menggunakan library yang menyertakan Aturan Keep yang bermasalah, Anda dapat memfilternya di file build.gradle.kts mulai dari AGP 9.0. Hal ini memberi tahu R8 untuk mengabaikan aturan yang berasal dari dependensi tertentu.

release {

    optimization.keepRules {

        // Ignore all consumer rules from this specific library

        it.ignoreFrom("com.somelibrary:somelibrary")

    }

}

Aturan Keep terbaik adalah tidak ada Aturan Keep

Strategi konfigurasi R8 terbaik adalah menghapus kebutuhan untuk menulis Aturan Keep sepenuhnya. Untuk banyak aplikasi, hal ini dapat dicapai dengan memilih library modern yang lebih mengutamakan pembuatan kode daripada refleksi. Dengan pembuatan kode, pengoptimal dapat lebih mudah menentukan kode mana yang benar-benar digunakan saat runtime dan kode mana yang dapat dihapus. Selain itu, tidak menggunakan refleksi dinamis berarti tidak ada titik entri "tersembunyi", dan oleh karena itu, tidak diperlukan Aturan Keep. Saat memilih library baru, selalu pilih solusi yang menggunakan pembuatan kode daripada refleksi.

Untuk mengetahui informasi selengkapnya tentang cara memilih library, lihat memilih library dengan bijak.

Men-debug dan memecahkan masalah konfigurasi R8

Jika R8 menghapus kode yang seharusnya dipertahankan, atau APK Anda lebih besar dari yang diharapkan, gunakan alat ini untuk mendiagnosis masalah.

Menemukan Aturan Keep duplikat dan global

Karena R8 menggabungkan aturan dari puluhan sumber, sulit untuk mengetahui kumpulan aturan "final". Menambahkan flag ini ke file proguard-rules.pro akan menghasilkan laporan lengkap:

# Outputs the final, merged set of rules to the specified file

-printconfiguration build/outputs/logs/configuration.txt

Anda dapat menelusuri file ini untuk menemukan aturan redundan atau melacak aturan yang bermasalah (seperti -dontoptimize) kembali ke library tertentu yang menyertakannya.

Tanyakan kepada R8: Mengapa Anda mempertahankan hal ini?

Jika class yang Anda harapkan dihapus masih ada di aplikasi Anda, R8 dapat memberi tahu Anda alasannya. Cukup tambahkan aturan ini:

# Asks R8 to explain why it's keeping a specific class

class com.example.MyUnusedClass

-whyareyoukeeping 

Selama build, R8 akan mencetak rantai referensi persis yang menyebabkannya mempertahankan class tersebut, sehingga Anda dapat melacak referensi dan menyesuaikan aturan.

Untuk panduan lengkap, lihat bagian memecahkan masalah R8.

Langkah berikutnya

R8 adalah alat yang efektif untuk meningkatkan performa aplikasi Android. Efektivitasnya bergantung pada pemahaman yang benar tentang operasinya sebagai mesin analisis statis.

Dengan menulis aturan tingkat anggota yang spesifik, memanfaatkan ancestor dan anotasi, serta memilih opsi keep yang tepat dengan cermat, Anda dapat mempertahankan hal yang benar-benar diperlukan. Praktik yang paling canggih adalah menghilangkan kebutuhan akan aturan sepenuhnya dengan memilih library modern berbasis codegen daripada pendahulunya berbasis refleksi.

Saat Anda mengikuti Minggu Sorotan Performa, pastikan untuk menonton video Minggu Sorotan hari ini di YouTube dan lanjutkan dengan tantangan R8 kami. Gunakan #optimizationEnabled untuk pertanyaan apa pun tentang cara mengaktifkan atau memecahkan masalah R8. Kami selalu siap membantu.

Saatnya melihat manfaatnya sendiri.

Kami menantang Anda untuk mengaktifkan mode penuh R8 untuk aplikasi Anda hari ini.

  1. Ikuti panduan developer kami untuk memulai: Mengaktifkan pengoptimalan aplikasi.
  2. Periksa apakah Anda masih menggunakan proguard-android.txt dan ganti dengan proguard-android-optimize.txt.
  3. Kemudian, ukur dampaknya. Jangan hanya merasakan perbedaannya, verifikasi. Ukur peningkatan performa Anda dengan mengadaptasi kode dari aplikasi contoh Macrobenchmark kami di GitHub untuk mengukur waktu startup Anda sebelum dan sesudah.

Kami yakin Anda akan melihat peningkatan yang signifikan dalam performa aplikasi Anda.

Saat melakukannya, gunakan tag sosial #AskAndroid untuk mengajukan pertanyaan. Sepanjang minggu ini, pakar kami akan memantau dan menjawab pertanyaan Anda.

Nantikan besok, saat kita akan membahas Pengoptimalan yang Dipandu Profil dengan Profil Dasar Pengukuran dan Startup, membagikan cara performa rendering Compose meningkat selama rilis terakhir, dan membagikan pertimbangan performa untuk tugas latar belakang.

Ditulis oleh:
Lanjutkan membaca