Действительно ли возможно поймать из исключения памяти в Java? [дубликат]

Они обычно - синонимы. Однако это зависит от приложения, которое Вы настраиваете. Пока приложение понимает то, что Вы имеете в виду, оно не должно приводить к потере производительности. По крайней мере, не один необходимо выкорчевать преждевременно, если Вы получаете мой дрейф.

52
задан jy. 6 November 2009 в 20:37
поделиться

9 ответов

Это не исключение; это ошибка: java.lang.OutOfMemoryError

Вы можете поймать его, поскольку он происходит от Throwable:

try {
    // create lots of objects here and stash them somewhere
} catch (OutOfMemoryError E) {
    // release some (all) of the above objects
}

Однако, если вы не делаете какие-то довольно специфические вещи (выделяете множество вещей в определенном разделе кода, например), вы, вероятно, не сможете поймать его так, как вы выиграли '

84
ответ дан 7 November 2019 в 08:58
поделиться

Это возможно:

try {
   // tragic logic created OOME, but we can blame it on lack of memory
} catch(OutOfMemoryError e) {
   // but what the hell will you do here :)
} finally {
   // get ready to be fired by your boss
}
53
ответ дан 7 November 2019 в 08:58
поделиться

Вы можете поймать и попытаться восстановить из исключений OutOfMemoryError (OOM), НО ЭТО ВЕРОЯТНО ПЛОХАЯ ИДЕЯ ... особенно если ваша цель - приложение чтобы «продолжать».

Для этого есть ряд причин:

  1. Как отмечали другие, есть лучшие способы управления ресурсами памяти, чем явное освобождение вещей; т.е. использование SoftReference и WeakReference для объектов, которые могут быть освобождены при нехватке памяти.

  2. Если вы дождетесь, пока у вас действительно не закончится память, прежде чем освобождать объекты, ваше приложение, вероятно, потратит больше времени на запуск сборщика мусора. В зависимости от вашей версии JVM и параметров настройки вашего GC JVM может в конечном итоге запускать GC все чаще и чаще по мере приближения к точке, в которой будет генерироваться OOM. Замедление (с точки зрения приложения, выполняющего полезную работу) может быть значительным. Вы, вероятно, захотите этого избежать.

  3. Если основная причина вашей проблемы - утечка памяти, то есть вероятность, что перехват и восстановление из OOM не восстановят утечку памяти. Ваше приложение будет продолжать работать некоторое время, затем снова и снова OOM, и снова, и снова с уменьшающимися интервалами.

Так что мой совет НЕ пытаться продолжать работу из OOM ... если вы не знаете :

  • где и почему произошло OOM,
  • что не было никакого «побочного ущерба», и
  • что ваше восстановление освободит достаточно памяти для продолжения.
25
ответ дан 7 November 2019 в 08:58
поделиться

Это возможно, но если у вас закончилась куча, это не очень полезно. Если есть ресурсы, которые можно освободить, вам лучше использовать SoftReference или WeakReference для таких ресурсов, и их очистка будет автоматической.

Я считаю полезным, если у вас закончится прямая память, прежде чем это не вызовет GC автоматически по какой-то причине. Так что у меня была причина принудительно выполнить gc, если я не смог выделить прямой буфер.

3
ответ дан 7 November 2019 в 08:58
поделиться

Можно перехватить любое исключение. Просто напишите

try{
   // code which you think might throw exception
}catch(java.lang.Throwable t){
   // you got the exception. Now what??
}

В идеале вы не должны ловить исключения java.lang.Error . Не улавливать такие исключения и позволить приложению завершить работу может быть лучшим решением, когда они возникают. Если вы думаете, что можете очень хорошо справиться с такими Ошибками, тогда вперед.

2
ответ дан 7 November 2019 в 08:58
поделиться

Конечно, перехват OutOfMemoryError разрешен. Убедитесь, что у вас есть план, что делать, когда это произойдет. Вам нужно будет освободить некоторую память (отбросив ссылки на объекты) перед выделением дополнительных объектов, иначе у вас снова закончится нехватка памяти. Иногда простой акт раскрутки стека на несколько кадров сделает это за вас, иногда вам нужно сделать что-то более явное.

1
ответ дан 7 November 2019 в 08:58
поделиться

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

Таким образом, лучший способ - создать / использовать кеш-память с учетом памяти. Есть несколько фреймворков (пример: JCS ), но вы можете легко создать свой собственный, используя SoftReference . О том, как им пользоваться, есть небольшая статья здесь . Перейдите по ссылкам в статье, чтобы получить дополнительную информацию.

8
ответ дан 7 November 2019 в 08:58
поделиться

Возможно, есть по крайней мере один подходящий момент, чтобы поймать OutOfMemoryError, когда вы специально выделяете что-то, что может быть слишком большим:

public static int[] decode(InputStream in, int len) throws IOException {
  int result[];
  try {
    result = new int[len];
  } catch (OutOfMemoryError e) {
    throw new IOException("Result too long to read into memory: " + len);
  } catch (NegativeArraySizeException e) {
    throw new IOException("Cannot read negative length: " + len);
  }
  ...
}
5
ответ дан 7 November 2019 в 08:58
поделиться

просто бросаю это для всех тех, кто размышляет о том, почему у кого-то может не хватать памяти: я работаю над проектом, у которого часто не хватает памяти, и мне пришлось реализовать решение для этого.

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

чтобы ускорить процесс обхода, мы стараемся держать как можно больше данных в физической памяти, но структуры данных растут по мере роста бинарного файла, и мы не можем держать их ВСЕ в памяти (цель - использовать кучу java меньше 256 м). что же делать?

я создал версии LinkedLists, Hashtables и т.д., хранящиеся на диске. они заменяют свои аналоги и реализуют все те же интерфейсы, поэтому со стороны выглядят идентично.

Разница? Эти структуры-заменители сотрудничают друг с другом, отлавливая ошибки нехватки памяти и запрашивая освобождение из памяти наименее недавно использованных элементов из наименее недавно использованной коллекции. Освобождение элемента сбрасывает его на диск во временный файл (в системный каталог temp) и помечает объекты-заместители как "paged-out" в соответствующей коллекции.

существует множество причин, по которым может закончиться память в java-приложении - корень большинства этих причин - одна или обе из: 1. Приложение работает на машине с ограниченными ресурсами (или пытается ограничить использование ресурсов путем ограничения размера кучи) 2. Приложение просто требует большого количества памяти (было предложено редактирование изображений, но как насчет аудио и видео? как насчет компиляторов, как в моем случае? как насчет долгосрочных сборщиков данных без энергонезависимой памяти?)

-bit

14
ответ дан 7 November 2019 в 08:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: