Android ランタイム(ART)でのアプリ動作の確認

Android ランタイム(ART)は、Android 搭載デバイス向けのデフォルトのランタイムです。 5.0(API レベル 21)以降。このランタイムには Android プラットフォームとアプリのパフォーマンスとスムーズさを向上させています。 ART の新機能について詳しくは、 ART

ただし、Dalvik で機能する一部の手法は ART では機能しません。この で、既存の VM プロバイダを移行する際に注意すべき点について 対応する必要があります。ほとんどのアプリは、Google Compute Engine で実行されている ART。

ガベージ コレクション(GC)の問題に対処する

Dalvik では、アプリが明示的に呼び出しを行うと、 System.gc(): ガベージ コレクション(GC)を要求します。これを ART を使用する場合(特にガベージ コレクションを呼び出す場合) GC_FOR_ALLOC タイプの 断片化を減らすために重要です使用中のランタイムと System.getProperty("java.vm.version") を呼び出します。ART が使用されている場合、プロパティの値 "2.0.0" 以上。

ART は、Java ヒープを同時に圧縮する同時コピー(CC)コレクタを使用します。 そのため、Terraform のような手法は使用しないでください。 GC の圧縮と互換性がない(オブジェクトへのポインタの保存など) インスタンス データなど)が含まれます。これは、 JNI(Java Native Interface)詳しくは、JNI の問題の防止をご覧ください。

JNI の問題の防止

ART の JNI は、Dalvik の JNI よりやや厳格です。これは特に CheckJNI モードを使用して一般的な問題をキャッチします。アプリで C/C++ 次の記事をご覧ください。

デバッグ Android JNI と CheckJNI の使用

JNI コードでガベージ コレクションの問題を確認する

同時コピー(CC)コレクタは、コンパクションのためにメモリ内のオブジェクトを移動することがあります。 C/C++ コードを使用する場合は、 GC の圧縮と互換性のない操作を実行する。Google は、 CheckJNI で潜在的な問題を特定(JNI を参照) ローカル参照の変更(ICS)をご覧ください)。

特に注目すべき領域の一つは Get...ArrayElements() および Release...ArrayElements() 使用できます。圧縮されていない GC を使用するランタイムでは、 Get...ArrayElements() 関数は通常、 配列オブジェクトの背後にある実際のメモリです。リージョンまたは 返された配列要素がある場合、配列オブジェクト自体が変更され Release...ArrayElements() までは無視されます)。ただし、 GC の圧縮が使用されている場合、Get...ArrayElements() 関数が メモリのコピーを返します。GC の圧縮時に参照を誤って使用すると、 メモリ破損などの問題が発生する可能性があります。例:

  • 返された配列要素に変更を加えた場合、 適切な Release...ArrayElements() 関数を実行します。 元のアカウントに変更内容が正しくコピーされ、 配列オブジェクトです。
  • メモリ配列要素を解放するときは、 次のモードになります。 <ph type="x-smartling-placeholder">
      </ph>
    • 配列要素を変更していない場合は、次のコマンドを使用します。 JNI_ABORT モード: コピーせずにメモリを解放します。 基になる配列オブジェクトに戻ります
    • 配列に変更を加えて、参照が不要な場合は、 さらに、コード 0 を使用します(配列オブジェクトが更新され、 。
    • commit する配列に変更を加えて、 配列のコピーを保持するには、JNI_COMMIT を使用します(これにより、 コピーを保持します)。
  • Release...ArrayElements() を呼び出すと、同じ 最初に Get...ArrayElements() によって返されたポインタ。対象 元のポインタをインクリメントすることは安全ではありません( 戻された配列要素)を渡して、増分されたポインタを Release...ArrayElements()。この変更されたポインタを渡すと、 間違ったメモリが解放され、メモリ破損につながります。

エラー処理

ART の JNI はエラーをスローするケースが多く、Dalvik ではスローされません。(1 回 このようなケースの多くは、CheckJNI でテストすることで捕捉できます)。

たとえば、RegisterNatives が呼び出されるメソッドが、 存在しない(メソッドが ProGuard)により、ART が NoSuchMethodError を適切にスローするようになりました。

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 がある場合、ART はエラー(logcat に表示)もログに記録します。 : メソッドなしで呼び出されます。

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

また、JNI 関数 GetFieldID()GetStaticFieldID()NoSuchFieldError を適切にスローするようになりました 単純に null を返すのではなく、同様に、GetMethodID()GetStaticMethodID()NoSuchMethodError を適切にスローするようになりました。 これにより、未処理の例外や ネイティブ コードの Java 呼び出し元には例外がスローされます。これにより、 CheckJNI モードで ART 互換アプリをテストする場合は特に重要です。

ART は JNI CallNonvirtual...Method() メソッドのユーザーを想定 (CallNonvirtualVoidMethod() など)を使用して、メソッドの宣言を使用する クラス(サブクラスではなく)を使用します。

スタックサイズの問題の防止

Dalvik には、ネイティブ コードと Java コード用に別々のスタックがあり、 スタックサイズは 32 KB、デフォルトのネイティブ スタックサイズは 1 MB です。ART は スタックを使用しています。通常、ART Thread スタックは Dalvik の場合とほぼ同じサイズにする必要があります。ただし、明示的に スタックサイズを設定するため、Google Cloud で実行するアプリでは、 ART。

  • Java で、明示的なスタックを指定する Thread コンストラクタの呼び出しを確認する 指定します。たとえば、StackOverflowError が発生した場合は、サイズを増やす必要があります。
  • C/C++ での pthread_attr_setstack() の使用と Java コードも実行するスレッドの場合は pthread_attr_setstacksize() JNI です。アプリが JNI を呼び出そうとしたときにログに記録されるエラーの例を以下に示します。 AttachCurrentThread(): pthread サイズが小さすぎる場合:
    F/art: art/runtime/thread.cc:435]
        Attempt to attach a thread with a too-small stack (16384 bytes)

オブジェクト モデルの変更

Dalvik は、package-private メソッドをオーバーライドするサブクラスを誤って許可していました。 次のような場合、ART は警告を発行します。

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

別のパッケージに含まれるクラスのメソッドをオーバーライドする場合は、 public または protected として指定できます。

Object に非公開フィールドが追加されました。野外活動を振り返るアプリ 自分のクラス階層内の他のグループを見てみると、 Object のフィールド。たとえば、あるクラスを反復処理する 階層構造をシリアライゼーション フレームワークの一部として組み込むと、

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

メソッドが null を返すまで続行するのではなく、

存在しない場合、プロキシ InvocationHandler.invoke()null を受け取るようになりました。 引数を渡します。この動作はすでに文書化されていますが、 Dalvik では正しく処理されません以前のバージョンの Mockito では、 そのため、ART でテストする際は最新の Mockito バージョンを使用してください。

AOT コンパイルの問題の解決

ART の事前(AOT)Java コンパイルは、すべての標準 Java で機能する できます。コンパイルは ART の dex2oat ツール関連する問題が発生した場合に インストール時に dex2oat された場合は、Google までお知らせください(問題の報告を参照)。速やかに修正いたします 必要があります。注意すべき問題がいくつかあります。

  • ART では、インストール時のバイトコード検証が Dalvik よりも厳格になっています。 Android ビルドツールによって生成されたコードは問題ありません。ただし、 後処理ツール(特に難読化を実行するツール)が原因で、 Dalvik では許容されるが ART では拒否される無効なファイル私たちは ツールベンダーと協力してこのような問題を見つけて修正します多くの場合、 DEX ファイルを再生成すると、これらの問題を修正できます 学習します
  • ART 検証ツールで報告される一般的な問題には、次のようなものがあります。 <ph type="x-smartling-placeholder">
      </ph>
    • 無効な制御フロー
    • 不均衡: monitorenter/monitorexit
    • 長さ 0 のパラメータ型のリストサイズ
  • 一部のアプリは、インストールされた .odex ファイルと依存関係があります 形式は /system/framework/data/dalvik-cacheDexClassLoader の最適化された出力ディレクトリ。これらの ファイルは拡張形式の DEX ファイルではなく、ELF ファイルになりました。ART が試行している間 ルールに従うため、アプリは Dalvik に依存せず、 制限します。形式は予告なく変更される場合があります。

    注: Android 8.0(API レベル 26)と それより上位の、DexClassLoader の最適化された出力ディレクトリ サポートが終了しました。詳細については、このモジュールの DexClassLoader() コンストラクタがあります。

問題の報告

アプリの JNI の問題が原因ではない問題に遭遇した場合は、 Android オープンソース プロジェクトの Issue Tracker(https://code.google.com/p/android/issues/list)から配布できます。 "adb bugreport" と、Google Play ストア(利用可能な場合)。それ以外の場合は、可能であれば、問題を再現する APK を 解決します。問題(添付ファイルを含む)は一般公開されることに注意してください 表示されます。