Неустранимое исключение: 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.