Android runtime (ART) adalah runtime default untuk perangkat yang menjalankan Android 5.0 (level API 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 di Memperkenalkan ART.
Akan tetapi, beberapa teknik yang berfungsi di Dalvik tidak berfungsi di ART. Ini dokumen memberi tahu Anda tentang hal-hal yang harus diperhatikan saat memigrasikan agar kompatibel dengan ART. Kebanyakan aplikasi akan berfungsi hanya saat dijalankan dengan ART.
Menangani Masalah Pengumpulan Sampah (GC)
Dalam Dalvik, aplikasi sering kali merasa berguna untuk memanggil secara eksplisit
System.gc()
untuk meminta pembersihan sampah memori (GC). Seharusnya,
jauh lebih tidak diperlukan dengan ART, terutama jika Anda memanggil pembersihan sampah memori
untuk mencegah jenis GC_FOR_ALLOC
kejadian 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 serentak memadatkan heap Java. Karena itu, Anda harus menghindari penggunaan teknik yang tidak kompatibel dengan GC pemadatan (seperti menyimpan pointer ke objek data instance). Hal ini khususnya 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. Ini adalah ide yang bagus menggunakan mode CheckJNI untuk menangkap masalah umum. Jika aplikasi Anda menggunakan C/C++ Anda harus meninjau artikel berikut:
Proses debug JNI Android dengan CheckJNI
Memeriksa kode JNI untuk masalah pengumpulan sampah
Kolektor Penyalinan Serentak (CC) dapat memindahkan objek dalam memori untuk pemadatan. Jika Anda menggunakan kode C/C++, jangan melakukan operasi yang tidak kompatibel dengan GC pemadatan. Kami telah meningkatkan CheckJNI untuk mengidentifikasi beberapa potensi masalah (seperti yang dijelaskan dalam JNI Perubahan Referensi Lokal di ICS).
Satu area yang harus diperhatikan
secara khusus adalah penggunaan
Get...ArrayElements()
dan Release...ArrayElements()
fungsi-fungsi lainnya. Dalam runtime dengan GC non-pemadatan,
Fungsi Get...ArrayElements()
biasanya menampilkan referensi ke
memori aktual yang mendukung objek array. Jika Anda mengubah salah satu
mengembalikan elemen array, objek array itu sendiri berubah (dan argumen
hingga Release...ArrayElements()
biasanya diabaikan). Namun, jika
GC pemadatan digunakan, fungsi Get...ArrayElements()
dapat
mengembalikan salinan memori. Jika Anda menyalahgunakan referensi
saat memadatkan GC
sedang digunakan, hal ini dapat menyebabkan
kerusakan memori atau masalah lainnya. Contoh:
- Jika Anda membuat perubahan pada elemen array yang ditampilkan, Anda harus memanggil metode
fungsi
Release...ArrayElements()
yang sesuai saat Anda selesai, untuk memastikan perubahan yang Anda buat disalin kembali dengan benar ke objek array. - Saat merilis elemen array memori, Anda harus menggunakan metode
bergantung pada perubahan yang telah Anda lakukan:
- Jika Anda tidak membuat perubahan apa pun pada elemen {i>array<i}, gunakan
Mode
JNI_ABORT
, yang melepaskan memori tanpa menyalin berubah kembali ke objek array yang mendasarinya. - Jika Anda membuat perubahan pada himpunan, dan tidak memerlukan referensi,
selengkapnya, gunakan kode
0
(yang memperbarui objek array dan mengosongkan salinan memori). - Jika Anda membuat perubahan pada array yang ingin di-commit, dan Anda ingin
untuk menyimpan salinan array, gunakan
JNI_COMMIT
(yang akan memperbarui objek array yang mendasarinya dan menyimpan salinannya).
- Jika Anda tidak membuat perubahan apa pun pada elemen {i>array<i}, gunakan
Mode
- Saat Anda memanggil
Release...ArrayElements()
, tampilkan respons yang sama pointer yang awalnya ditampilkan olehGet...ArrayElements()
. Sebagai tidak aman menambah pointer asli (untuk memindai melalui elemen array yang ditampilkan) lalu meneruskan pointer yang bertambah keRelease...ArrayElements()
. Meneruskan pointer yang dimodifikasi ini dapat menyebabkan membebaskan memori yang salah, sehingga menyebabkan kerusakan memori.
Penanganan error
JNI ART menampilkan kesalahan dalam beberapa kasus, sedangkan Dalvik tidak demikian. (Sekali 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 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 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()
sekarang menampilkan NoSuchFieldError
dengan benar
alih-alih hanya mengembalikan {i>null<i}. Demikian pula, GetMethodID()
dan
GetStaticMethodID()
sekarang menampilkan NoSuchMethodError
dengan benar.
Ini bisa menyebabkan kegagalan CheckJNI karena pengecualian yang tidak tertangani atau
diterapkan 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()
) untuk menggunakan deklarasi metode
, bukan subclass, seperti yang diwajibkan oleh spesifikasi JNI.
Mencegah masalah ukuran tumpukan
Dalvik memiliki tumpukan terpisah untuk kode asli dan Java, dengan Java default
ukuran stack 32 KB dan ukuran stack native default 1 MB. ART memiliki
menumpuk untuk lokalitas yang lebih baik. Biasanya, stack Thread
ART
harus hampir sama dengan Dalvik. Namun, jika Anda secara eksplisit
menyetel ukuran tumpukan, Anda mungkin perlu meninjau kembali nilai-nilai tersebut untuk aplikasi yang berjalan di
ART.
- Di Java, tinjau panggilan ke konstruktor
Thread
yang menentukan stack eksplisit ukuran. Misalnya, Anda harus menambah ukuran jikaStackOverflowError
muncul. - Di C/C++, tinjau penggunaan
pthread_attr_setstack()
danpthread_attr_setstacksize()
untuk thread yang juga menjalankan kode Java melalui untuk JNI. Berikut contoh error yang dicatat 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 kelasnya harus berhati-hati agar tidak mencoba melihat
kolom Object
. Misalnya, jika Anda melakukan iterasi pada class
sebagai bagian dari framework serialisasi, berhenti ketika
Class.getSuperclass() == java.lang.Object.class
alih-alih melanjutkan hingga metode menampilkan null
.
Proxy InvocationHandler.invoke()
kini menerima null
jika tidak ada
argumen, bukan array kosong. Perilaku ini didokumentasikan
sebelumnya tetapi
tidak ditangani dengan benar di Dalvik. Mockito versi sebelumnya mengalami kesulitan dengan
jadi gunakan versi Mockito yang telah diperbarui saat menguji dengan ART.
Memperbaiki masalah kompilasi AOT
Kompilasi Java Ahead-Of-Time (AOT) dari ART seharusnya berfungsi untuk semua aplikasi Java
pada kode sumber. Kompilasi dilakukan oleh ART
Alat dex2oat
; jika Anda mengalami masalah
yang terkait dengan
dex2oat
pada waktu penginstalan, beri tahu kami (lihat Melaporkan Masalah) agar kami dapat memperbaikinya dengan cepat
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 alat pascapemrosesan (terutama alat yang melakukan obfuscation) dapat menghasilkan file tidak valid yang ditoleransi oleh Dalvik namun ditolak oleh ART. Kami telah bekerja sama dengan vendor alat untuk menemukan dan memperbaiki masalah tersebut. Dalam banyak kasus, versi terbaru dari alat Anda dan membuat ulang file DEX dapat memperbaiki menyelesaikan semua jenis permasalahan.
- Beberapa masalah umum yang ditandai oleh pemverifikasi ART antara lain:
- alur kontrol tidak valid
monitorenter
/monitorexit
tidak seimbang- ukuran daftar tipe parameter dengan panjang 0
- Beberapa aplikasi memiliki dependensi pada file
.odex
yang terinstal dalam format/system/framework
,/data/dalvik-cache
, atau di direktori outputDexClassLoader
yang dioptimalkan. Ini sekarang adalah file ELF dan bukan bentuk perluasan dari file DEX. Saat ART mencoba mengikuti aturan penamaan dan penguncian yang sama dengan Dalvik, aplikasi tidak boleh bergantung dalam format {i>file<i}; format ini dapat berubah tanpa pemberitahuan.Catatan: Di Android 8.0 (level API 26) dan lebih tinggi, direktori output yang dioptimalkan untuk
DexClassLoader
tidak digunakan lagi. Untuk informasi selengkapnya, lihat dokumentasi untukDexClassLoader()
.
Melaporkan masalah
Jika Anda mengalami masalah yang bukan disebabkan oleh masalah JNI aplikasi, laporkan
mereka melalui Android Open Source Project Issue Tracker 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
menyelesaikan masalah. Perlu diketahui bahwa masalah (termasuk lampiran) bersifat publik
terlihat.