Die Android-Laufzeit (ART) ist die Standardlaufzeit für Geräte mit Android. 5.0 (API-Level 21) und höher. Diese Laufzeit bietet eine Reihe von Funktionen die die Leistung und reibungslose Abläufe der Android-Plattform und -Apps verbessern. Weitere Informationen zu den neuen Funktionen von ART finden Sie unter Einführung ART
Einige Techniken, die auf Dalvik funktionieren, funktionieren jedoch nicht bei ART. Dieses Dokument enthält Informationen darüber, worauf Sie beim Migrieren eines vorhandenen App mit ART kompatibel sein. Die meisten Apps sollten funktionieren, wenn sie mit KUNST.
Probleme mit der automatischen Speicherbereinigung beheben
Unter Dalvik finden Apps häufig nützlich,
System.gc()
, um die automatische Speicherbereinigung aufzurufen. Dies sollte
weitaus weniger notwendig mit ART, insbesondere wenn Sie die automatische Speicherbereinigung aufrufen.
um den Typ GC_FOR_ALLOC
zu verhindern
oder Fragmentierung reduzieren. Sie können prüfen, welche Laufzeit verwendet wird,
indem du System.getProperty("java.vm.version")
anrufst. Wenn ART verwendet wird, wird der Wert der Eigenschaft
ist "2.0.0"
oder höher.
ART verwendet den Collector Concurrent Copy (CC), der gleichzeitig den Java-Heap verdichtet. Daher sollten Sie es vermeiden, die nicht mit der GC-Komprimierung kompatibel sind, z. B. das Speichern von Verweisen auf das Objekt Instanzdaten). Dies ist besonders wichtig für Apps, bei denen das Java Native Interface (JNI). Weitere Informationen finden Sie unter JNI-Probleme verhindern.
JNI-Probleme vermeiden
Die JNI von ART ist etwas strenger als die von Dalvik. Besonders gut ist es, den CheckJNI-Modus verwenden, um häufige Probleme zu erkennen. Wenn Ihre App C/C++ nutzt erhalten Sie im folgenden Artikel:
Fehlerbehebung Android JNI mit CheckJNI
JNI-Code auf Probleme bei der automatischen Speicherbereinigung prüfen
Der Collector für gleichzeitige Kopiervorgänge kann zur Verdichtung Objekte in den Arbeitsspeicher verschieben. Wenn Sie C/C++ Code verwenden, Vorgänge ausführen, die mit der Verdichtung von GC nicht kompatibel sind. Wir haben die CheckJNI ein, um potenzielle Probleme zu identifizieren (wie in JNI beschrieben) Änderungen bei lokalen Referenzen in ICS
Achten Sie insbesondere auf die Verwendung von
Get...ArrayElements()
und Release...ArrayElements()
Funktionen. In Laufzeiten mit nicht verdichtender Speicherbereinigung (GC)
Get...ArrayElements()
-Funktionen geben normalerweise einen Verweis auf die
tatsächlichen Arbeitsspeicher, der das Array-Objekt stützt. Wenn Sie eine Änderung an einer der
Array-Elemente zurückgegeben hat, wird das Array-Objekt selbst geändert (und die Argumente
bis Release...ArrayElements()
werden normalerweise ignoriert. Wenn jedoch
GC verdichtet wird, können die Get...ArrayElements()
-Funktionen
um eine Kopie der Erinnerung zurückzugeben. Wenn du die Referenz bei der Verdichtung von GC missbrauchst,
verwendet wird, kann dies zu Speicherbeschädigungen oder anderen Problemen führen. Beispiel:
- Wenn Sie Änderungen an den zurückgegebenen Array-Elementen vornehmen, müssen Sie die Methode
Release...ArrayElements()
-Funktion hinzu, sobald Sie fertig sind, damit die vorgenommenen Änderungen korrekt in die zugrunde liegende Array-Objekt enthält. - Wenn Sie die Elemente des Speicherarrays freigeben, müssen Sie die entsprechenden
je nachdem, welche Änderungen Sie vorgenommen haben:
<ph type="x-smartling-placeholder">
- </ph>
- Wenn Sie keine Änderungen an den Array-Elementen vorgenommen haben, verwenden Sie
Der
JNI_ABORT
-Modus, der den Arbeitsspeicher freigibt, ohne zu kopieren in das zugrunde liegende Array-Objekt zurück. - Wenn Sie Änderungen am Array vorgenommen haben und keinen Verweis benötigen
Verwenden Sie außerdem den Code
0
. Dieser aktualisiert das Array-Objekt und gibt die Kopie der Erinnerung). - Wenn Sie Änderungen am Array vorgenommen haben, für das Sie einen Commit durchführen möchten,
Um die Kopie des Arrays zu behalten, verwenden Sie
JNI_COMMIT
, wodurch das zugrunde liegende Array-Objekt und behält die Kopie bei).
- Wenn Sie keine Änderungen an den Array-Elementen vorgenommen haben, verwenden Sie
Der
- Wenn Sie
Release...ArrayElements()
aufrufen, geben Sie Folgendes zurück: Zeiger, der ursprünglich vonGet...ArrayElements()
zurückgegeben wurde. Für ist es nicht sicher, den ursprünglichen Zeiger zu erhöhen, zurückgegebene Array-Elemente), übergeben Sie dann den erhöhten Zeiger anRelease...ArrayElements()
Wird dieser geänderte Zeiger übergeben, falschen Arbeitsspeicher freigegeben werden, was zu Speicherbeschädigungen führt.
Fehlerbehandlung
Die JNI von ART gibt in einigen Fällen Fehler aus, in denen Dalvik dies nicht tut. (Einmal Auch hier können Sie viele solcher Fälle durch Tests mit CheckJNI erkennen.)
Wenn beispielsweise RegisterNatives
mit einer Methode aufgerufen wird,
nicht existiert (möglicherweise weil die Methode von einem Tool wie
ProGuard), wirft ART jetzt NoSuchMethodError
ordnungsgemäß aus:
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 protokolliert auch einen Fehler (sichtbar in Logcat), wenn RegisterNatives
ohne Methoden aufgerufen:
W/art ( 1234): JNI RegisterNativeMethods: attempt to register 0 native methods for <classname>
Darüber hinaus können die JNI-Funktionen GetFieldID()
und
GetStaticFieldID()
wirft NoSuchFieldError
jetzt korrekt
anstatt einfach null zurückzugeben. Entsprechend werden GetMethodID()
und
GetStaticMethodID()
wirft NoSuchMethodError
jetzt korrekt.
Dies kann aufgrund der unbehandelten Ausnahmen oder der
die an Java-Aufrufer von nativem Code ausgegeben werden. So können Sie
besonders wichtig, um ART-kompatible Apps mit dem CheckJNI-Modus zu testen.
ART erwartet Nutzer der JNI CallNonvirtual...Method()
-Methoden
(z. B. CallNonvirtualVoidMethod()
), um die Deklaration der Methode zu verwenden
keine abgeleitete Klasse, wie von der JNI-Spezifikation gefordert.
Probleme mit der Stackgröße vermeiden
Dalvik hatte separate Stacks für nativen Code und Java-Code, mit einem Standard-Java-
Stackgröße von 32 KB und eine standardmäßige native Stackgröße von 1 MB. ART hat eine einheitliche
für eine bessere Lokalität. Normalerweise ist der ART-Thread
-Stapel
sollte ungefähr der Größe von Dalvik entsprechen. Wenn Sie jedoch ausdrücklich
Stackgrößen festlegen, müssen Sie diese Werte für Apps, die in
KUNST.
- Prüfen Sie in Java die Aufrufe des
Thread
-Konstruktors, die einen expliziten Stack angeben. Größe. Sie müssen die Größe beispielsweise erhöhen, wennStackOverflowError
auftritt. - Prüfen Sie die Verwendung von
pthread_attr_setstack()
undpthread_attr_setstacksize()
für Threads, die auch Java-Code ausführen über JNI. Hier ist ein Beispiel für einen protokollierten Fehler, wenn eine Anwendung versucht, JNI aufzurufenAttachCurrentThread()
, wenn die pthread-Größe zu klein ist:F/art: art/runtime/thread.cc:435] Attempt to attach a thread with a too-small stack (16384 bytes)
Änderungen am Objektmodell
Dalvik erlaubte fälschlicherweise Unterklassen, private Paketmethoden zu überschreiben. ART gibt in folgenden Fällen eine Warnung aus:
Before Android 4.1, method void com.foo.Bar.quux() would have incorrectly overridden the package-private method in com.quux.Quux
Wenn Sie die Methode einer Klasse in einem anderen Paket überschreiben möchten, deklarieren Sie die Methode
als public
oder protected
.
Object
hat jetzt private Felder. Apps, die Felder reflektieren
in ihren Klassenhierarchien nicht versuchen,
Felder von Object
. Wenn Sie z. B. eine Klasse iterieren,
Hierarchie als Teil eines Serialisierungsframeworks
Class.getSuperclass() == java.lang.Object.class
anstatt fortzufahren, bis die Methode null
zurückgibt.
Proxy InvocationHandler.invoke()
empfängt jetzt null
, wenn keine
anstelle eines leeren Arrays. Dieses Verhalten wurde bereits dokumentiert,
in Dalvik nicht richtig gehandhabt wird. In früheren Versionen von Mockito gibt es
Verwenden Sie also beim Testen mit ART eine aktualisierte Mockito-Version.
Probleme bei der AOT-Kompilierung beheben
Die AOT-Java-Kompilierung von ART von ART sollte für alle Standard-Java funktionieren
Code. Die Zusammenstellung erfolgt von ARTs
dex2oat
-Tool; falls Probleme im Zusammenhang mit
dex2oat
bei der Installation an, damit wir sie schnellstmöglich beheben können (siehe Probleme melden).
wie möglich. Beachten Sie die folgenden Punkte:
- ART führt bei der Installation eine strengere Bytecode-Überprüfung als Dalvik durch. Code, der von den Android-Build-Tools erstellt wird, sollte in Ordnung sein. Einige (insbesondere Tools zur Verschleierung) ungültige Dateien, die von Dalvik toleriert, aber von ART abgelehnt wurden. Wir haben und arbeiten mit den Toolanbietern zusammen, um solche Probleme zu finden und zu beheben. In vielen Fällen die neuesten Versionen Ihrer Tools und das Neugenerieren der DEX-Dateien kann dieses Problem beheben. Probleme.
- Zu den typischen Problemen, die von der ART-Verifizierung gemeldet werden, gehören:
<ph type="x-smartling-placeholder">
- </ph>
- Ungültiger Kontrollablauf
- unausgeglichen
monitorenter
/monitorexit
- Listengröße der Parametertypen mit Länge 0
- Einige Anwendungen haben Abhängigkeiten von der installierten
.odex
-Datei Format/system/framework
,/data/dalvik-cache
oder im optimierten Ausgabeverzeichnis vonDexClassLoader
. Diese -Dateien sind jetzt ELF-Dateien und keine erweiterte Form von DEX-Dateien. Während ART versucht, dieselben Benennungs- und Sperrregeln wie bei Dalvik. zum Dateiformat; kann das Format ohne vorherige Ankündigung geändert werden.Hinweis:Unter Android 8.0 (API-Level 26) und höher, das optimierte Ausgabeverzeichnis für
DexClassLoader
wurde eingestellt. Weitere Informationen finden Sie in der Dokumentation zumDexClassLoader()
-Konstruktor.
Probleme bei der Berichterstellung
Wenn Probleme auftreten, die nicht auf JNI-Probleme mit der App zurückzuführen sind, melden Sie
Nutzen Sie den Issue Tracker für das Android Open Source Project unter https://code.google.com/p/android/issues/list.
Füge eine "adb bugreport"
und einen Link zur App im Google
Play Store, falls verfügbar. Hängen Sie andernfalls, falls möglich, ein APK an, das die
das Problem zu lösen. Hinweis: Probleme (einschließlich Anhängen) sind öffentlich.
sichtbar sind.