Можно ли исключить исключение из памяти в java?

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

Ответ 1

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

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

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

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

Ответ 2

Возможно:

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
}

Ответ 3

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

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

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

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

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

Итак, мой совет - НЕ пытаться уходить от OOM... если вы не знаете:

  • где и почему произошел OOM,
  • что не было бы никакого "побочного ущерба" и
  • чтобы ваше восстановление выпустило достаточно памяти для продолжения.

Ответ 4

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

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

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

я создал резервные копии LinkedLists, Hashtables и т.д. Это замены для своих копий и реализации всех тех же интерфейсов, которые выглядят одинаково из внешнего мира.

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

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

-битных

Ответ 5

Можно поймать OutOfMemoryError (It a Error, а не Exception), но вы должны знать, что нет способа получить определенное поведение.
Вы даже можете получить еще один OutOfMemoryError, пытаясь поймать его.

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

Ответ 6

Возможно, по крайней мере одно подходящее время, чтобы поймать 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);
  }
  ...
}

Ответ 7

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

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

Ответ 8

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

Ответ 9

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

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

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