Неустранимое исключение: java.lang.OutOfMemoryError: int[] длиной 1083403672 превышает ограничение виртуальной машины

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");

...

Любая идея, почему это происходит при извлечении дополнительных из намерения?

1 ответ

Когда вы сталкиваетесь с java.lang.OutOfMemoryError: размер запрашиваемого массива превышает лимит виртуальной машины, это означает, что приложение, аварийно завершающее работу с ошибкой, пытается выделить массив больше, чем может поддерживать виртуальная машина Java.

Ошибка генерируется собственным кодом в JVM. Это происходит перед выделением памяти для массива, когда JVM выполняет специфичную для платформы проверку: адресуема ли выделенная структура данных на этой платформе. Эта ошибка встречается реже, чем вы могли подумать.

Причина, по которой вы редко сталкиваетесь с этой ошибкой, заключается в том, что массивы Java индексируются с помощью int. Максимальное положительное значение int в Java составляет 2^31-1 = 2 147 483 647. И ограничения для конкретной платформы могут быть очень близки к этому числу - например, на моем 64-битном MB Pro на Java 1.7 я могу с радостью инициализировать массивы максимум с 2 147 483 645 или элементами Integer.MAX_VALUE-2.

Увеличение длины массива на единицу до Integer.MAX_VALUE-1 приводит к знакомому исключению OutOfMemoryError в потоке "main" java.lang.OutOfMemoryError: размер запрашиваемого массива превышает ограничение виртуальной машины

Каково решение?

Java.lang.OutOfMemoryError: Запрошенный размер массива превышает ограничение виртуальной машины может появиться в результате одной из следующих ситуаций:

Ваши массивы становятся слишком большими и в конечном итоге имеют размер между пределом платформы и Integer.MAX_INT

Вы намеренно пытаетесь выделить массивы, превышающие 2^31-1 элементов, чтобы поэкспериментировать с ограничениями.

В первом случае проверьте свою кодовую базу, чтобы увидеть, действительно ли вам нужны такие большие массивы. Может быть, вы могли бы уменьшить размер массивов и покончить с этим. Или разделите массив на более мелкие куски и загрузите данные, с которыми вам нужно работать, партиями, вписываясь в ограничение вашей платформы.

Во втором случае - помните, что массивы Java индексируются с помощью int. Таким образом, вы не можете выходить за пределы 2^31-1 элементов в ваших массивах при использовании стандартных структур данных на платформе. Фактически, в этом случае вы уже заблокированы компилятором, который объявляет "ошибка: слишком большое целое число" во время компиляции.

Но если вы действительно работаете с действительно большими наборами данных, вам нужно пересмотреть свои варианты. Вы можете загружать данные, с которыми вам нужно работать, небольшими партиями и при этом использовать стандартные инструменты Java, или вы можете выйти за рамки стандартных утилит. Один из способов добиться этого - заглянуть в класс sun.misc.Unsafe. Это позволяет вам выделять память напрямую, как в C.

Другие вопросы по тегам