4
Fatal Exception: java.lang.OutOfMemoryError: int[] of length 1083403672 exceeds the VM limit
   at android.util.ArrayMap.allocArrays(ArrayMap.java:196)
   at android.util.ArrayMap.ensureCapacity(ArrayMap.java:307)
   at android.os.Bundle.unparcel(Bundle.java:247)
   at android.os.Bundle.getString(Bundle.java:1118)
   at com.test.example.pushnotification.LocalyticsReceiver.handleNotificationReceived(LocalyticsReceiver.java:61)
   at com.test.example.pushnotification.LocalyticsReceiver.onReceive(LocalyticsReceiver.java:52)
   at android.app.ActivityThread.handleReceiver(ActivityThread.java:2426)
   at android.app.ActivityThread.access$1700(ActivityThread.java:139)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1276)
   at android.os.Handler.dispatchMessage(Handler.java:102)
   at android.os.Looper.loop(Looper.java:136)
   at android.app.ActivityThread.main(ActivityThread.java:5103)

それが指すコード:-

String message = intent.getExtras().getString("message");

以下のコードのスナップショットを見つけてください。

 @Override
    public void onReceive(Context context, Intent intent) {

        String appKey = context.getResources().getString(R.string.localytics_api_key);
        if (!TextUtils.isEmpty(appKey)) {
            Localytics.integrate(context.getApplicationContext(), appKey);
        }

        if (intent.getAction().equals("com.google.android.c2dm.intent.REGISTRATION")) {
            LocalyticsUtil.handleRegistration(intent);
        } else {
            Localytics.handlePushNotificationReceived(intent);
            handleNotificationReceived(context, intent);
        }
    }

    //handle notification when received
    private void handleNotificationReceived(Context context, Intent intent) {


        // Get the notification message
        String message = intent.getExtras().getString("message");

...

インテントから余分なものを取得しているときに発生する理由はありますか?

4

1 に答える 1

0

java.lang.OutOfMemoryError: Requested array size exceeded VM limit に直面した場合、これは、エラーでクラッシュしたアプリケーションが、Java 仮想マシンがサポートできるよりも大きな配列を割り当てようとしていることを意味します。

エラーは、JVM 内のネイティブ コードによってスローされます。これは、JVM がプラットフォーム固有のチェック (割り当てられたデータ構造がこのプラットフォームでアドレス指定可能かどうか) を実行するときに、配列にメモリを割り当てる前に発生します。このエラーは、最初に考えたほど一般的ではありません。

このエラーにめったに直面しない理由は、Java 配列が int によってインデックス付けされるためです。Java の正の整数の最大値は 2^31 – 1 = 2,147,483,647 です。また、プラットフォーム固有の制限は、この数値に非常に近い場合があります。たとえば、私の 64 ビット MB Pro on Java 1.7 では、配列を最大 2,147,483,645 または Integer.MAX_VALUE-2 要素で問題なく初期化できます。

配列の長さを 1 ずつ増やして Integer.MAX_VALUE-1 にすると、おなじみの OutOfMemoryError Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeded VM limit が発生します

解決策は何ですか?

java.lang.OutOfMemoryError: Requested array size exceeded VM limit は、次のいずれかの状況の結果として表示される可能性があります。

配列が大きくなりすぎて、プラットフォームの制限と Integer.MAX_INT の間のサイズになってしまう

制限を試すために、意図的に 2^31-1 要素より大きい配列を割り当てようとします。

最初のケースでは、コード ベースをチェックして、それほど大きな配列が本当に必要かどうかを確認します。たぶん、配列のサイズを縮小して、それで完了することができます。または、配列をより小さなバルクに分割し、プラットフォームの制限に合わせてバッチで処理する必要があるデータをロードします。

2 番目のケースでは、Java 配列は int によってインデックス付けされることに注意してください。したがって、プラットフォーム内で標準のデータ構造を使用する場合、配列内の 2^31-1 要素を超えることはできません。実際、この場合、コンパイル中に「エラー: 整数が大きすぎます」と通知するコンパイラによって既にブロックされています。

しかし、本当に大規模なデータ セットを扱う場合は、オプションを再考する必要があります。作業に必要なデータを小さなバッチでロードして、標準の Java ツールを使用することも、標準のユーティリティを超えることもできます。これを実現する 1 つの方法は、sun.misc.Unsafe クラスを調べることです。これにより、C で行うようにメモリを直接割り当てることができます。

于 2016-08-11T05:50:33.507 に答える