Android çalışma zamanında (ART) uygulama davranışını doğrulama

Android çalışma zamanı (ART), Android çalıştıran cihazlar için varsayılan çalışma zamanıdır 5.0 (API düzeyi 21) ve sonraki sürümler. Bu çalışma zamanı bir dizi özellik sunar. . ART'ın yeni özellikleri hakkında daha fazla bilgiyi ART.

Ancak Dalvik'te işe yarayan bazı teknikler ART'ta işe yaramaz. Bu doküman, mevcut bir dosyayı taşırken dikkat etmeniz gereken şeyler hakkında sizi uygulamasını ART ile uyumlu hale getirin. Çoğu uygulama ART.

Atık toplama (GC) sorunlarını ele alma

Dalvik altında, uygulamalar çoğu zaman açıkça telefon etmeyi faydalı bulur Atık toplama (GC) istemi için System.gc(). Bu özellik, özellikle atık toplama işlemi yapıyorsanız ART ile çok daha az GC_FOR_ALLOC türünü önlemek için kullanılması anlamına gelir. Hangi çalışma zamanının kullanılmakta olduğunu doğrulayabilirsiniz System.getProperty("java.vm.version") numaralı telefonu arayarak. ART kullanılıyorsa mülkün değeri "2.0.0" veya daha yüksek.

ART, Java yığınını eşzamanlı olarak sıkıştıran Eşzamanlı Kopyalama (CC) toplayıcısını kullanır. Bu nedenle, tekniklerin kullanımı sıkıştırmak için GC ile uyumlu olmayan (imleçleri nesneye kaydetme gibi) örnek verileri) görebilirsiniz. Bu, özellikle Java Native Interface (JNI). Daha fazla bilgi için JNI Sorunlarını Önleme bölümüne bakın.

JNI sorunlarını önleme

ART'ın JNI'si, Dalvik'inkinden biraz daha katı. Bu, özellikle de sık karşılaşılan sorunları yakalamak için CheckJNI modunu kullanmanızı öneririz. Uygulamanız C/C++ kullanıyorsa aşağıdaki makaleyi incelemelisiniz:

Hata ayıklama CheckJNI ile Android JNI

Atık toplama sorunları için JNI kodunu kontrol etme

Eşzamanlı Kopyalama (CC) toplayıcısı, sıkıştırma için bellekteki nesneleri taşıyabilir. C/C++ kodu kullanıyorsanız GC'yi sıkıştırmayla uyumlu olmayan işlemler gerçekleştirme. Gelişmiş Bazı olası sorunları tanımlamak için CheckJNI'yı kontrol edin (JNI'da açıklandığı gibi) ICS'deki Yerel Referans Değişiklikleri).

Özellikle dikkat edilmesi gereken bir alan, Get...ArrayElements() Release...ArrayElements() işlevlerine dahildir. Kompakt olmayan GC ile çalışma zamanlarında, Get...ArrayElements() işlevleri genellikle dizi nesnesini destekleyen gerçek bellekte yer alır. Anahtar kelimelerinizden birinde dizi öğeleri döndürüldüğünde, dizi nesnesinin kendisi değiştirilmiş (ve bağımsız değişkenlerin Release...ArrayElements() ifadeleri genellikle yoksayılır). Ancak, sıkıştırma GC kullanımdaysa Get...ArrayElements() işlevleri belleğin bir kopyasını alabilirsiniz. GC'yi sıkıştırırken referansı kötüye kullanırsanız kullanılması bellek bozulmasına veya başka sorunlara yol açabilir. Örnek:

  • Döndürülen dizi öğelerinde herhangi bir değişiklik yaparsanız uygun Release...ArrayElements() işlevini kullanın, yaptığınız değişikliklerin temel alınan reklama doğru kopyalandığından dizi nesnesini anlatacağım.
  • Bellek dizisi öğelerini serbest bıraktığınızda, modunu seçin:
    • Dizi öğelerinde herhangi bir değişiklik yapmadıysanız JNI_ABORT modu, kopyalamadan belleği serbest bırakır temel dizi nesnesine dönüşür.
    • Dizide değişiklik yaptıysanız ve herhangi bir referansa ihtiyacınız yoksa için dizi nesnesini güncelleyen ve serbest bırakan 0 kodunu kullanın. anının kopyası) ekleyebilirsiniz.
    • Kaydetmek istediğiniz dizide değişiklikler yaptıysanız ve dizinin kopyasını saklamak için JNI_COMMIT (güncellenen) alt dizi nesnesini oluşturur ve kopyayı saklar).
  • Release...ArrayElements() adlı kişiyi aradığınızda aynı şekilde geri dönün ilk olarak Get...ArrayElements() tarafından döndürülen işaretçi. Örneğin, Örneğin, orijinal işaretçiyi artırmak güvenli değildir (örneğin, dizi öğeleri döndürüldüğünden emin olun) ardından artırılmış işaretçiyi Release...ArrayElements() Bu değiştirilmiş işaretçiyi aktarmak, bellekte bozulmaya yol açabilir.

Hata işleme

ART'ın JNI hizmeti, Dalvik'in göndermediği birçok durumda hata bildirmektedir. (Bir kez Bu tür durumların çoğunu CheckJNI ile test ederek yakalayabilirsiniz.)

Örneğin, RegisterNatives mevcut değildir (belki de yöntemin ProGuard), ART artık NoSuchMethodError öğesini düzgün şekilde fırlatıyor:

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)

RegisterNatives, şu durumda bir hata da kaydeder (logcat'te görünür) yöntem olmadan çağrıldı:

W/art     ( 1234): JNI RegisterNativeMethods: attempt to register 0 native
methods for <classname>

Buna ek olarak JNI, GetFieldID() ve GetStaticFieldID() artık düzgün bir şekilde NoSuchFieldError atıyor değerini döndürür. Benzer şekilde, GetMethodID() ve GetStaticMethodID() artık düzgün bir şekilde NoSuchMethodError atıyor. Bu durum, işlenmeyen istisnalar veya yerel kodun Java çağrıcılarına atılan istisnalar. Bu da, ART ile uyumlu uygulamaların CheckJNI moduyla test edilmesi özellikle önemlidir.

ART, JNI CallNonvirtual...Method() yöntemlerini kullanmasını bekler (ör. CallNonvirtualVoidMethod()) sınıfını kullanır.

Yığın boyutu sorunlarını önleme

Dalvik, varsayılan Java ile yerel ve Java kodu için ayrı yığınlara sahipti grup boyutu 32 KB ve varsayılan yerel grup boyutu 1 MB'tır. ART, daha iyi bir yerleşim yeri kullanabilirsiniz. Normalde, ART Thread grubu yaklaşık olarak Dalvik ile aynı olmalıdır. Ancak, açık bir şekilde veya başka bir yerde çalışan uygulamalar için bu değerleri ART.

  • Java'da, açık bir yığın belirten Thread oluşturucuya yapılan çağrıları inceleyin seçin. Örneğin, StackOverflowError gerçekleşirse boyutu artırmanız gerekir.
  • C/C++'ta, pthread_attr_setstack() ve Java kodu da çalıştıran iş parçacıkları için pthread_attr_setstacksize() JNI Bir uygulama JNI'yi çağırmaya çalıştığında günlüğe kaydedilen hatanın örneğini burada bulabilirsiniz pthread boyutu çok küçük olduğunda AttachCurrentThread():
    F/art: art/runtime/thread.cc:435]
        Attempt to attach a thread with a too-small stack (16384 bytes)

Nesne modeli değişiklikleri

Dalvik, alt sınıfların gizli paket yöntemlerini geçersiz kılmasına yanlışlıkla izin verdi. ART, aşağıdaki durumlarda uyarı gönderir:

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

Bir sınıfın yöntemini farklı bir pakette geçersiz kılmak istiyorsanız yöntemini public veya protected olarak ayarlayın.

Object artık özel alanlara sahip. Alanları yansıtan uygulamalar kendi sınıf hiyerarşilerinde, Object alanları. Örneğin, bir sınıfı geliştiriyorsanız bir serileştirme çerçevesinin parçası olarak hiyerarşik

Class.getSuperclass() == java.lang.Object.class

yerine null değerini döndürür.

InvocationHandler.invoke() proxy'sinull bağımsız değişkenlerini kullanır. Bu davranış daha önce belgelenmiş olsa da içeren bir e-posta alırsınız. Mockito'nun önceki sürümlerinde Bu nedenle, ART ile test yaparken güncellenmiş bir Mockito sürümünü kullanın.

AOT derleme sorunlarını düzeltme

ART'ın Ahead-Of-Time (AOT) Java derlemesi, tüm standart Java uygulamaları için çalışır girin. Derleme, ART tarafından gerçekleştirilir dex2oat aracı; dex2oat, yükleme sırasında bize bildirin (Raporlama Sorunları'na bakın). Böylece, sorunları en kısa sürede çözebiliriz. yardımcı olabilirsiniz. Göz önünde bulundurulması gereken birkaç sorun:

  • ART, yükleme sırasında Dalvik'inkinden daha sıkı bayt kodu doğrulaması yapar. Android derleme araçları tarafından oluşturulan kod sorunsuz olmalıdır. Ancak bazı işleme sonrası araçları (özellikle kod karartma işlemi yapan araçlar) Dalvik tarafından tolere edilen ancak ART tarafından reddedilen geçersiz dosyalar. Bir süredir araç tedarikçileriyle birlikte çalışarak bu tür sorunları tespit edip giderebilirsiniz. Çoğu durumda, son haline getirmek ve DEX dosyalarını yeniden oluşturmak bu sorunları giderebilir. neden olabilir.
  • ART doğrulayıcısı tarafından işaretlenen bazı tipik sorunlar şunlardır:
    • geçersiz kontrol akışı
    • dengesiz monitorenter/monitorexit
    • 0 uzunluklu parametre türü liste boyutu
  • Bazı uygulamaların yüklü .odex dosyasına bağımlılıkları var biçimi /system/framework, /data/dalvik-cache veya DexClassLoader optimize edilmiş çıkış dizininde. Bu dosyaları artık genişletilmiş bir DEX dosyası biçimi değil, ELF dosyalarıdır. ART, ile aynı adlandırma ve kilitleme kurallarına uymasını gerektirirse, uygulamalar dosya biçiminde olmalıdır; bildirimde bulunulmadan değiştirilebilir.

    Not: Android 8.0 (API düzeyi 26) ve daha yüksek, DexClassLoader için optimize edilmiş çıkış dizini desteği sonlandırıldı. Daha fazla bilgi için DexClassLoader(). kurucusu.

Raporlama sorunları

Uygulama JNI sorunlarından kaynaklanmayan bir sorunla karşılaşırsanız https://code.google.com/p/android/issues/list adresindeki Android Açık Kaynak Proje Sorun Takip Aracı üzerinden iletebilirsiniz. Google'a bir "adb bugreport" ve uygulamanın bağlantısını ekleyin Varsa Play Store. Aksi takdirde, mümkünse düşünmesi gerekir. Sorunların (ekler dahil) herkese açık olduğunu unutmayın görünür.