lightbulb_outline Please take our October 2018 developer survey. Start survey

Memverifikasi Perilaku Aplikasi pada Android Runtime (ART)

Android Runtime (ART) adalah waktu proses default untuk perangkat yang menjalankan Android 5.0 (API level 21) dan yang lebih tinggi. Waktu proses ini menawarkan sejumlah fitur yang meningkatkan kinerja dan kemulusan aplikasi serta platform Android. Anda bisa menemukan informasi selengkapnya tentang fitur baru ART dalam Memperkenalkan ART.

Akan tetapi, beberapa teknik yang berfungsi di Dalvik tidak berfungsi di ART. Dokumen ini memungkinkan Anda mengetahui tentang hal-hal yang harus diperhatikan saat migrasi aplikasi yang ada agar kompatibel dengan ART. Kebanyakan aplikasi akan berfungsi begitu saja saat dijalankan bersama ART.

Menangani Masalah Pengumpulan Sampah (GC)

Pada Dalvik, aplikasi sering kali akan merasakan gunanya memanggil System.gc() secara eksplisit untuk mengonfirmasi pengumpulan sampah (GC). Hal ini akan menjadi kurang begitu dibutuhkan pada ART, khususnya jika Anda memanggil pengumpulan sampah untuk mencegah terjadinya GC bertipe GC_FOR_ALLOC atau untuk mengurangi fragmentasi. Anda bisa memverifikasi waktu proses mana yang sedang digunakan dengan memanggil System.getProperty("java.vm.version"). Jika ART sedang digunakan, nilai properti adalah "2.0.0" atau yang lebih tinggi.

Lebih jauh, pengumpul sampah pemadatan sedang dalam tahap development di Android Open-Source Project (AOSP) untuk meningkatkan manajemen memori. Karenanya, Anda harus menghindari penggunaan teknik-teknik yang tidak kompatibel dengan GC pemadatan (misalnya menyimpan pointer ke data instance objek). Ini khususnya penting bagi aplikasi yang menggunakan Java Native Interface (JNI). Untuk informasi selengkapnya, lihat Mencegah Masalah JNI.

Mencegah Masalah JNI

JNI ART kadang-kadang lebih ketat daripada JNI Dalvik. Ini adalah ide yang bagus sekali menggunakan mode CheckJNI untuk menangkap masalah umum. Jika aplikasi Anda menggunakan kode C/C++, Anda harus memeriksa artikel berikut:

Men-debug Android JNI dengan CheckJNI

Memeriksa kode JNI untuk masalah pengumpulan sampah

ART memiliki pengumpul sampah pemadatan yang sedang dalam tahap development di Android Open Source Project (AOSP). Setelah pengumpul sampah pemadatan sedang digunakan, objek mungkin akan dipindah di memori. Jika Anda menggunakan kode C/C++, jangan lakukan operasi yang tidak kompatibel dengan GC pemadatan. Kami telah menyempurnakan CheckJNI untuk mengidentifikasi beberapa masalah potensial (seperti yang dijelaskan dalam Perubahan Referensi Lokal JNI dalam ICS).

Satu area yang harus diperhatikan secara khusus adalah penggunaan fungsi Get...ArrayElements() dan Release...ArrayElements(). Di waktu proses yang memiliki GC non-pemadatan, fungsi Get...ArrayElements() biasanya mengembalikan referensi ke memori sesungguhnya yang mendukung objek larik. Jika Anda membuat perubahan pada salah satu elemen larik yang dikembalikan, objek larik dengan sendirinya berubah (dan argumen ke Release...ArrayElements() biasanya diabaikan). Akan tetapi, jika GC pemadatan digunakan, fungsi Get...ArrayElements() mungkin akan mengembalikan salinan memori. Jika Anda menyalahgunakan referensi saat GC pemadatan sedang digunakan, ini bisa menyebabkan korupsi memori atau masalah lainnya. Misalnya:

  • Jika Anda membuat perubahan pada elemen larik yang dikembalikan, Anda harus memanggil fungsi Release...ArrayElements() yang sesuai bila Anda telah selesai, untuk memastikan perubahan yang Anda buat telah disalin kembali dengan benar ke objek larik sumbernya.
  • Bila Anda merilis elemen larik memori, Anda harus menggunakan mode yang sesuai, bergantung pada perubahan yang Anda buat:
    • Jika Anda tidak membuat perubahan apa pun pada elemen larik, gunakan mode JNI_ABORT, yang merilis memori tanpa menyalin perubahan kembali ke objek larik sumbernya.
    • Jika Anda membuat perubahan pada larik, dan tidak memerlukan referensi lagi, gunakan kode 0 (yang memperbarui objek larik dan membebaskan salinan memori).
    • Jika Anda membuat perubahan pada larik yang ingin Anda ikat, dan ingin mempertahankan salinan larik, gunakan JNI_COMMIT (yang memperbarui objek larik sumbernya dan mempertahankan salinannya).
  • Bila Anda memanggil Release...ArrayElements(), akan mengembalikan pointer yang sama dengan yang semula dikembalikan oleh Get...ArrayElements(). Misalnya, tidak aman menambah pointer asal (untuk memindai melalui elemen larik yang dikembalikan) kemudian meneruskan pointer yang telah ditambahi ke Release...ArrayElements(). Meneruskan pointer yang telah dimodifikasi ini bisa menyebabkan salah membebaskan memori, sehingga mengakibatkan korupsi memori.

Penanganan kesalahan

JNI ART akan melontarkan kesalahan dalam sejumlah kasus sedangkan Dalvik tidak demikian. (Sekali lagi, Anda bisa 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 melontarkan 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 kesalahan (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 melontarkan NoSuchFieldError dengan benar, sebagai ganti sekadar mengembalikan nol. Demikian pula, GetMethodID() dan GetStaticMethodID() kini melontarkan NoSuchMethodError dengan benar. Ini bisa menyebabkan CheckJNI gagal karena pengecualian yang tidak tertangani atau pengecualian dilontarkan ke pemanggil Java kode asli. Ini membuatnya sangat penting untuk menguji aplikasi yang kompatibel dengan ART menggunakan mode CheckJNI.

ART mengharapkan pengguna metode CallNonvirtual...Method() JNI (misalnya CallNonvirtualVoidMethod()) untuk menggunakan kelas pendeklarasi metode, bukan subkelas, sebagaimana diharuskan oleh spesifikasi JNI.

Mencegah Masalah Ukuran Tumpukan

Dalvik memiliki tumpukan terpisah untuk kode asli dan Java, dengan ukuran tumpukan Java default sebesar 32 KB dan ukuran tumpukan asli default 1 MB. ART memiliki tumpukan terpadu demi lokalitas yang lebih baik. Umumnya, ukuran tumpukan Thread ART kurang lebih sama dengan Dalvik. Akan tetapi, jika Anda secara eksplisit menyetel ukuran tumpukan, Anda mungkin perlu mempertimbangkan kembali nilai-nilai itu untuk aplikasi yang berjalan di ART.

  • Di Java, tinjau panggilan ke konstruktor Thread yang menetapkan ukuran tumpukan eksplisit. Misalnya, Anda nanti perlu menambah ukuran jika StackOverflowError terjadi.
  • Di C/C++, tinjau penggunaan pthread_attr_setstack() dan pthread_attr_setstacksize() untuk thread yang juga menjalankan kode Java lewat JNI. Inilah contoh kesalahan yang tercatat dalam log bila aplikasi berusaha memanggil JNI AttachCurrentThread() bila 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 memperbolehkan subkelas untuk menggantikan metode privat-paket. ART mengeluarkan peringatan dalam kasus demikian:

Before Android 4.1, method void com.foo.Bar.quux()
would have incorrectly overridden the package-private method in
com.quux.Quux

Jika Anda bermaksud mengganti metode kelas dalam paket berbeda, deklarasikan metode sebagai public atau protected.

Object kini memiliki bidang-bidang privat. Aplikasi yang mencerminkan bidang-bidang dalam hierarki kelasnya harus berhati-hati agar tidak berusaha melihat bidang-bidang Object. Misalnya, jika Anda mengulang hierarki kelas sebagai bagian kerangka kerja serialisasi, hentikan bila

Class.getSuperclass() == java.lang.Object.class
sebagai ganti melanjutkannya hingga metode tersebut mengembalikan null.

Proxy InvocationHandler.invoke() kini menerima null jika tidak ada argumen sebagai ganti larik kosong. Perilaku ini sebelumnya telah didokumentasikan namun tidak ditangani dengan benar di Dalvik. Mockito versi sebelumnya mengalami kesulitan dengan hal ini, jadi gunakan versi Mockito yang telah diperbarui saat menguji dengan ART.

Memperbaiki Masalah Kompilasi AOT

Kompilasi Java Ahead-Of-Time (AOT) di ART seharusnya berhasil untuk semua kode standar Java. Kompilasi dilakukan oleh alat dex2oat ART; jika Anda mengalami masalah yang berkaitan dengan dex2oat pada waktu pemasangan, beri tahu kami (lihat Melaporkan Masalah) jadi kami bisa 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. Akan tetapi, sebagian alat pascapemrosesan (khususnya alat yang melakukan pengaburan) mungkin menghasilkan file tidak valid yang ditoleransi oleh Dalvik namun ditolak oleh ART. Kami sedang bekerja sama dengan vendor alat untuk menemukan dan memperbaiki masalah demikian. Di banyak kasus, mendapatkan versi terbaru alat Anda dan membuat kembali file DEX bisa memperbaiki masalah-masalah ini.
  • Sebagian masalah umum yang telah ditandai oleh pemverifikasi ART antara lain:
    • alur kontrol tidak valid
    • moniterenter/moniterexit yang tidak seimbang
    • ukuran daftar tipe parameter dengan panjang 0
  • Sebagian aplikasi memiliki dependensi pada format file .odex yang dipasang di /system/framework, /data/dalvik-cache, atau dalam direktori keluaran yang dioptimalkan DexClassLoader. Semua file ini sekarang adalah file ELF dan bukan bentuk perluasan dari file DEX. Walaupun ART mencoba mengikuti penamaan dan aturan penguncian yang sama dengan Dalvik, aplikasi tidak boleh bergantung pada format file; format tersebut dapat berubah tanpa pemberitahuan.
  • Melaporkan Masalah

    Jika Anda mengalami masalah yang bukan diakibatkan oleh masalah JNI aplikasi, laporkan masalah itu lewat Android Open Source Project Issue Tracker di https://code.google.com/p/android/issues/list. Sertakan "adb bugreport" dan tautan ke aplikasi tersebut di Google Play Store jika tersedia. Jika tidak maka, bila memungkinkan, lampirkan APK yang menirukan masalah tersebut. Perhatikan, masalah-masalah itu (termasuk lampiran) bisa dilihat oleh umum.