Memory exceptions in java

Is it possible to catch out of memory exception in java? [duplicate]

I’m developing a program that would require huge amount of memory, and I want to catch when out-of-memory exception happens. I had heard this is not possible to do, but curious if there is any development on this end.

Asking how to handle running out of memory is not quite the same as asking whether it is possible to catch an OutOfMemoryError . So this is not quite a duplicate of How to handle OutOfMemoryError in Java.

9 Answers 9

It’s not an exception; it’s an error: java.lang.OutOfMemoryError

You can catch it as it descends from Throwable:

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

However, unless you’re doing some rather specific stuff (allocating tons of things within a specific code section, for example) you likely won’t be able to catch it as you won’t know where it’s going to be thrown from.

@matt b — in the specific case where you’re able to catch it you’re presumably trying to control your memory consumption and thus would be able to release some / all of it. But generally speaking you’re right, of course.

@ChssPly76 (and others) — please read my answer to understand why trying to manage memory consumption by catching OOME’s would be a BAD IDEA.

Читайте также:  Api java android studio

@BaldbcsofIT — Your assertion that there is no alternative is incorrect. There is always an alternative: restart the JVM.

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 >

There is at least one reasonable thing which you could be doing which causes an OOME and is recoverable: Loading a very large image. The only thing in the try block is a call to ImageIO.read(), and you’re showing the user a dialog telling them that the image is too large in the catch block. Just saying.

@uckelman That’s a wrong approach, unless your app is single threaded. The thing is that even though your image-loading-thread catches OOME, but the other threads dont know about this and can get an OOME too

@SurajChandran: The OOME caused by attempting to load a very large image will be due to attempting to allocate a very large byte[] or int[] . You get an OOME from that because the allocation fails, not because you are actually out of memory—hence it won’t cause a problem on other threads.

You can catch and attempt to recover from OutOfMemoryError (OOM) exceptions, BUT IT IS PROBABLY A BAD IDEA . especially if your aim is for the application to «keep going».

There are a number of reasons for this:

  1. As others have pointed out, there are better ways to manage memory resources than explicitly freeing things; i.e. using SoftReference and WeakReference for objects that could be freed if memory is short.
  2. If you wait until you actually run out of memory before freeing things, your application is likely to spend more time running the garbage collector. Depending on your JVM version and on your GC tuning parameters, the JVM can end up running the GC more and more frequently as it approaches the point at which will throw an OOM. The slowdown (in terms of the application doing useful work) can be significant. You probably want to avoid this.
  3. If the root cause of your problem is a memory leak, then the chances are that catching and recovering from the OOM will not reclaim the leaked memory. You application will keep going for a bit then OOM again, and again, and again at ever reducing intervals.

So my advice is NOT attempt to keep going from an OOM . unless you know:

  • where and why the OOM happened,
  • that there won’t have been any «collateral damage», and
  • that your recovery will release enough memory to continue.

That may be OK. It depends. The concern is that the infrastructure (in the JVM) for talking to the monitoring system might itself have been damaged by the out of memory state. So even sending the metric could lock up things.

just throwing this out there for all those who ponder why someone might be running out of memory: i’m working on a project that runs out of memory frequently and i have had to implement a solution for this.

the project is a component of a forensics and investigation app. after collecting data in the field (using very low memory footprint, btw) data is opened in our investigation app. one of the features is to perform a CFG traversal of any arbitrary binary image that was captured in the field (applications from physical memory). these traversals can take a long time, but produce very helpful visual representations of the binary that was traversed.

to speed the traversal process, we try to keep as much data in physical memory as possible, but the data structures grow as the binary grows and we cannot keep it ALL in memory (the goal is to use a java heap less than 256m). so what do i do?

i created disk-backed versions of LinkedLists, Hashtables, etc. these are drop-in replacements for their counterparts and implement all the same interfaces so they look identical from the outside world.

the difference? these replacement structures cooperate with each other, catching out of memory errors and requesting that the least recently used elements from the least recently used collection be freed from memory. freeing the element dumps it to disk in temporary file (in the system provided temp directory) and marks a placeholder objects as «paged-out» in the proper collection.

there are PLENTY of reasons you might run out of memory in a java app — the root of most of these reasons is either one or both of: 1. App runs on a resource constrained machine (or attempts to limit resource usage by limiting heap size) 2. App simply requires large amounts of memory (image editing was suggested, but how about audio and video? what about compilers like in my case? how about long-term data collectors without non-volatile storage?)

Источник

Какие бывают типы OutOfMemoryError или из каких частей состоит память java процесса

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

image

Область памяти, занимаемая java процессом, состоит из нескольких частей. Тип OutOfMemoryError зависит от того, в какой из них не хватило места.

1. java.lang.OutOfMemoryError: Java heap space

Не хватает место в куче, а именно, в области памяти в которую помещаются объекты, создаваемые программно в вашем приложении. Размер задается параметрами -Xms и -Xmx. Если вы пытаетесь создать объект, а места в куче не осталось, то получаете эту ошибку. Обычно проблема кроется в утечке памяти, коих бывает великое множество, и интернет просто пестрит статьями на эту тему.

2. java.lang.OutOfMemoryError: PermGen space

Данная ошибка возникает при нехватке места в Permanent области, размер которой задается параметрами -XX:PermSize и -XX:MaxPermSize. Что там лежит и как бороться с OutOfMemoryError возникающей там, я уже описал подробнейшим образом тут.

3. java.lang.OutOfMemoryError: GC overhead limit exceeded

Данная ошибка может возникнуть как при переполнении первой, так и второй областей. Связана она с тем, что памяти осталось мало и GC постоянно работает, пытаясь высвободить немного места. Данную ошибку можно отключить с помощью параметра -XX:-UseGCOverheadLimit, но, конечно же, её надо не отключать, а либо решать проблему утечки памяти, либо выделять больше объема, либо менять настройки GC.

4. java.lang.OutOfMemoryError: unable to create new native thread

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

На самом деле это очень просто воспроизвести на windows на 32-битной машине, так как там процессу выделяется не больше 2Гб.

Допустим у вас есть приложение с большим количеством одновременно работающих пользователей, которое запускается с параметрами -Xmx1024M -XX:MaxPermSize=256M -Xss512K. Если всего процессу доступно 2G, то остается свободным еще коло 768M. Именно в данном остатке памяти и создаются стеки потоков. Таким образом, примерно вы можете создать не больше 768*(1024/512)=1536 (у меня при таких параметрах получилось создать 1316) нитей (см. рисунок в начале статьи), после чего вы получите OutOfMemoryError. Если вы увеличиваете -Xmx, то количество потоков, которые вы можете создать соответственно уменьшается. Вариант с уменьшением -Xss, для возможности создания большего количества потоков, не всегда выход, так как, возможно, у вас существуют в системе потоки требующие довольно больших стеков. Например, поток инициализации или какие-нибудь фоновые задачи. Но все же выход есть. Оказывается при программном создании потока, можно указать размер стека: Thread(ThreadGroup group, Runnable target, String name,long stackSize). Таким образом вы можете выставить -Xss довольно маленьким, а действия требующие больших стеков, выполнять в отдельных потоках, созданных с помощью упомянутого выше конструктора.

Более подробно, что же лежит в стеке потока, и куда уходит эта память, можно прочитать тут.

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

Источник

Оцените статью