Android runtime (ART) adalah runtime default untuk perangkat yang menjalankan Android 5.0 (API level 21) dan yang lebih tinggi. Runtime ini menawarkan sejumlah fitur yang meningkatkan performa dan kelancaran platform dan aplikasi Android. Anda dapat menemukan informasi selengkapnya tentang fitur baru ART dalam Memperkenalkan ART.
Akan tetapi, beberapa teknik yang berfungsi di Dalvik tidak berfungsi di ART. Dokumen ini memberi tahu Anda tentang hal-hal yang harus diperhatikan saat memigrasikan aplikasi yang ada agar kompatibel dengan ART. Sebagian besar aplikasi akan berfungsi begitu saja saat dijalankan bersama ART.
Menangani Masalah Pengumpulan Sampah (GC)
Pada Dalvik, aplikasi sering kali perlu memanggil
System.gc()
secara eksplisit untuk meminta pembersihan sampah memori (GC). Hal ini akan
menjadi jauh lebih tidak diperlukan dengan ART, terutama jika Anda memanggil pembersihan sampah memori
untuk mencegah kemunculan jenis GC_FOR_ALLOC
atau untuk mengurangi fragmentasi. Anda dapat memverifikasi runtime mana yang sedang digunakan
dengan memanggil System.getProperty("java.vm.version")
. Jika ART sedang digunakan, nilai properti
adalah "2.0.0"
atau lebih tinggi.
ART menggunakan kolektor Concurrent Menyalin (CC) yang secara serentak memadatkan heap Java. Karena itu, Anda harus menghindari penggunaan teknik yang tidak kompatibel dengan GC pemadatan (seperti menyimpan pointer ke data instance objek). Hal ini sangat penting bagi aplikasi yang menggunakan Java Native Interface (JNI). Untuk mengetahui informasi selengkapnya, lihat Mencegah Masalah JNI.
Mencegah Masalah JNI
JNI ART agak lebih ketat daripada JNI Dalvik. Menggunakan mode CheckJNI lebih baik untuk menangkap masalah umum. Jika aplikasi Anda menggunakan kode C/C++, Anda harus meninjau artikel berikut:
Men-debug Android JNI dengan CheckJNI
Memeriksa kode JNI untuk masalah pengumpulan sampah
Kolektor Concurrent Menyalin (CC) dapat memindahkan objek dalam memori untuk pemadatan. Jika Anda menggunakan kode C/C++, jangan lakukan operasi yang tidak kompatibel dengan GC pemadatan. Kami telah meningkatkan CheckJNI untuk mengidentifikasi beberapa potensi masalah (seperti yang dijelaskan dalam Perubahan Referensi Lokal JNI di ICS).
Satu area yang harus diperhatikan secara khusus adalah penggunaan fungsi
Get...ArrayElements()
dan
Release...ArrayElements()
. Pada runtime dengan GC non-pemadatan, fungsi Get...ArrayElements()
biasanya menampilkan referensi ke
memori sebenarnya yang mendukung objek array. Jika Anda melakukan perubahan pada salah satu
elemen array yang ditampilkan, objek array itu sendiri akan berubah (dan argumen
ke Release...ArrayElements()
biasanya diabaikan). Namun, jika
GC pemadatan digunakan, fungsi Get...ArrayElements()
dapat
menampilkan salinan memori. Jika Anda menyalahgunakan referensi saat GC pemadatan
sedang digunakan, hal ini dapat menyebabkan kerusakan memori atau masalah lainnya. Contoh:
- Jika membuat perubahan pada elemen array yang ditampilkan, Anda harus memanggil
fungsi
Release...ArrayElements()
yang sesuai setelah selesai, untuk memastikan perubahan yang Anda buat telah disalin kembali dengan benar ke objek array yang mendasarinya. - Saat merilis elemen array memori, Anda harus menggunakan mode yang sesuai, bergantung pada perubahan yang Anda buat:
- Jika Anda tidak membuat perubahan apa pun pada elemen array, gunakan
mode
JNI_ABORT
, yang merilis memori tanpa menyalin perubahan kembali ke objek array yang mendasarinya. - Jika Anda membuat perubahan pada array, dan tidak memerlukan referensi lagi, gunakan kode
0
(yang memperbarui objek array dan membebaskan salinan memori). - Jika Anda membuat perubahan pada array yang ingin di-commit, dan ingin
menyimpan salinan array, gunakan
JNI_COMMIT
(yang mengupdate objek array yang mendasarinya dan mempertahankan salinannya).
- Jika Anda tidak membuat perubahan apa pun pada elemen array, gunakan
mode
- Saat Anda memanggil
Release...ArrayElements()
, tampilkan pointer yang sama dengan yang awalnya ditampilkan olehGet...ArrayElements()
. Misalnya, tidak aman untuk menambah pointer asli (untuk memindai melalui elemen array yang ditampilkan), lalu meneruskan pointer yang bertambah keRelease...ArrayElements()
. Meneruskan pointer yang telah dimodifikasi ini dapat menyebabkan salah membebaskan memori, sehingga mengakibatkan kerusakan memori.
Penanganan error
JNI ART melempar error dalam sejumlah kasus, sedangkan Dalvik tidak demikian. (Sekali lagi, Anda dapat menangkap banyak kasus demikian dengan mengujinya menggunakan CheckJNI.)
Misalnya, jika RegisterNatives
dipanggil dengan metode yang
tidak ada (mungkin karena metode tersebut telah dihapus oleh alat seperti
ProGuard), ART kini akan menampilkan NoSuchMethodError
dengan benar:
08-12 17:09:41.082 13823 13823 E AndroidRuntime: FATAL EXCEPTION: main 08-12 17:09:41.082 13823 13823 E AndroidRuntime: java.lang.NoSuchMethodError: no static or non-static method "Lcom/foo/Bar;.native_frob(Ljava/lang/String;)I" 08-12 17:09:41.082 13823 13823 E AndroidRuntime: at java.lang.Runtime.nativeLoad(Native Method) 08-12 17:09:41.082 13823 13823 E AndroidRuntime: at java.lang.Runtime.doLoad(Runtime.java:421) 08-12 17:09:41.082 13823 13823 E AndroidRuntime: at java.lang.Runtime.loadLibrary(Runtime.java:362) 08-12 17:09:41.082 13823 13823 E AndroidRuntime: at java.lang.System.loadLibrary(System.java:526)
ART juga akan mencatat error (terlihat di logcat) jika RegisterNatives
dipanggil tanpa metode:
W/art ( 1234): JNI RegisterNativeMethods: attempt to register 0 native methods for <classname>
Selain itu, fungsi JNI GetFieldID()
dan
GetStaticFieldID()
kini menampilkan NoSuchFieldError
dengan benar,
bukan hanya menampilkan null. Demikian pula, GetMethodID()
dan
GetStaticMethodID()
kini akan menampilkan NoSuchMethodError
dengan benar.
Hal ini dapat menyebabkan CheckJNI gagal karena pengecualian yang tidak tertangani atau
pengecualian ditampilkan ke pemanggil Java kode native. Hal ini membuatnya
sangat penting untuk menguji aplikasi yang kompatibel dengan ART menggunakan mode CheckJNI.
ART mengharapkan pengguna metode CallNonvirtual...Method()
JNI
(seperti CallNonvirtualVoidMethod()
) menggunakan class deklarasi
metode, bukan subclass, seperti yang diwajibkan oleh spesifikasi JNI.
Mencegah masalah ukuran tumpukan
Dalvik memiliki stack terpisah untuk kode native dan Java, dengan ukuran stack Java default sebesar 32 KB dan ukuran stack native default sebesar 1 MB. ART memiliki tumpukan terpadu
untuk lokalitas yang lebih baik. Biasanya, ukuran stack Thread
ART
kurang lebih sama dengan Dalvik. Namun, jika Anda secara eksplisit
menetapkan ukuran tumpukan, Anda mungkin perlu meninjau kembali nilai tersebut untuk aplikasi yang berjalan di
ART.
- Di Java, tinjau panggilan ke konstruktor
Thread
yang menentukan ukuran stack eksplisit. Misalnya, Anda perlu meningkatkan ukuran jikaStackOverflowError
terjadi. - Pada C/C++, tinjau penggunaan
pthread_attr_setstack()
danpthread_attr_setstacksize()
untuk thread yang juga menjalankan kode Java melalui JNI. Berikut adalah contoh error yang dicatat ke dalam log saat aplikasi mencoba memanggil JNIAttachCurrentThread()
jika ukuran pthread terlalu kecil:F/art: art/runtime/thread.cc:435] Attempt to attach a thread with a too-small stack (16384 bytes)
Perubahan model objek
Dalvik salah mengizinkan subclass untuk menimpa metode pribadi paket. ART mengeluarkan peringatan dalam beberapa kasus seperti:
Before Android 4.1, method void com.foo.Bar.quux() would have incorrectly overridden the package-private method in com.quux.Quux
Jika Anda ingin mengganti metode class dalam paket lain, deklarasikan
metode sebagai public
atau protected
.
Object
kini memiliki kolom pribadi. Aplikasi yang mencerminkan kolom
dalam hierarki class-nya harus berhati-hati agar tidak mencoba melihat
kolom Object
. Misalnya, jika Anda melakukan iterasi hierarki
class sebagai bagian dari framework serialisasi, hentikan saat
Class.getSuperclass() == java.lang.Object.class
bukan melanjutkan hingga metode menampilkan null
.
Proxy InvocationHandler.invoke()
kini menerima null
jika tidak ada
argumen, bukan array kosong. Perilaku ini sebelumnya telah didokumentasikan, tetapi
tidak ditangani dengan benar di Dalvik. Mockito versi sebelumnya mengalami kesulitan dengan
hal ini, jadi gunakan versi Mockito yang telah diupdate saat menguji dengan ART.
Memperbaiki masalah kompilasi AOT
Kompilasi Java Ahead-Of-Time (AOT) di ART seharusnya berfungsi untuk semua kode Java
standar. Kompilasi dilakukan oleh alat
dex2oat
ART. Jika Anda mengalami masalah terkait
dex2oat
pada waktu penginstalan, beri tahu kami (lihat Melaporkan Masalah) agar kami dapat memperbaikinya secepat
mungkin. Dua masalah yang harus diperhatikan:
- ART melakukan verifikasi bytecode pada waktu pemasangan yang lebih ketat daripada Dalvik. Kode yang dihasilkan oleh alat pembangun Android seharusnya berhasil. Namun, beberapa fitur pascapemrosesan (terutama fitur yang melakukan obfuscation) dapat menghasilkan file tidak valid yang ditoleransi oleh Dalvik tetapi ditolak oleh ART. Kami telah bekerja sama dengan vendor alat untuk menemukan dan memperbaiki masalah tersebut. Dalam banyak kasus, mendapatkan versi terbaru alat dan membuat ulang file DEX dapat memperbaiki masalah ini.
- Beberapa masalah umum yang ditandai oleh pemverifikasi ART meliputi:
- alur kontrol tidak valid
monitorenter
/monitorexit
tidak seimbang- ukuran daftar tipe parameter dengan panjang 0
- Beberapa aplikasi memiliki dependensi pada format file
.odex
yang diinstal di/system/framework
,/data/dalvik-cache
, atau di direktori output yang dioptimalkanDexClassLoader
. Semua file ini sekarang adalah file ELF dan bukan bentuk perluasan dari file DEX. Meskipun ART mencoba mengikuti penamaan dan aturan penguncian yang sama dengan Dalvik, aplikasi tidak boleh bergantung pada format file; format dapat berubah tanpa pemberitahuan.Catatan: Di Android 8.0 (API level 26) dan yang lebih tinggi, direktori output yang dioptimalkan
DexClassLoader
tidak digunakan lagi. Untuk informasi selengkapnya, lihat dokumentasi untuk konstruktorDexClassLoader()
.
Melaporkan masalah
Jika Anda mengalami masalah yang bukan karena masalah JNI aplikasi, laporkan
masalah tersebut melalui Issue Tracker Project Open Source Android di https://code.google.com/p/android/issues/list.
Sertakan "adb bugreport"
dan link ke aplikasi di Google
Play Store jika tersedia. Jika tidak, jika memungkinkan, lampirkan APK yang mereproduksi
masalah. Perlu diperhatikan bahwa masalah (termasuk lampiran) dapat dilihat
oleh publik.