This discussion is archived
1 2 3 4 Previous Next 57 Replies Latest reply: Jan 13, 2006 1:56 PM by 807590 Go to original post RSS
  • 30. Re: How to catch OutOfMemoryError?
    807592 Newbie
    Currently Being Moderated
    endasil wrote:
    jhandl wrote:
    Not using threads is not an option.
    And why not?
    Are you trying to build something that is fast or just "cool"?
    Are you really suggesting that threads serve no useful purpose?
    No, he's suggesting that there are cases of actual programs that aren't multithreaded. This shouldn't come as a shock.
    Oh, I misinterpreted his remarks. Sorry. The fact is, though, that I have valid reasons to use threads.
    I know it looks like I'm just venting my frustration, and I am, but I came here in the hope that there is an answer, some technique I haven't heard of that helps keep the OOME in check. Sorry if I'm wasting your time.
    Don't be sorry. This kind of debate is healthy when it's not simply trolling.
    I hope I'm not comming accross as a troll.
  • 31. Re: How to catch OutOfMemoryError?
    jschellSomeoneStoleMyAlias Expert
    Currently Being Moderated
    I don't agree with the idea though, because the only thing it would let you clean up are static references (unless your "freeMemory()" method had access to the entire heap of objects), so basically it would only be able to gain memory through freeing globally referenced objects
    Err... in terms of my example.

    Then that is incorrect.

    In the catch block you can do something like cleaning a large cache - that has nothing to do with 'static references'. And if you did that then running the task, presuming it wasn't filling the cache in the first place, would then work.
    Let's end this discussion with the Java API:
    Yes, and again if I know what my application is doing then that is meaningless. If I know that I have in fact allocated a large amount of memory which can safely be disposed of then I can in fact deal with a OOME.
  • 32. Re: How to catch OutOfMemoryError?
    jschellSomeoneStoleMyAlias Expert
    Currently Being Moderated
    Are you really suggesting that threads serve no useful purpose?
    I am suggesting that in my experience from this site that people that talk in absolutes and then suggest that java is broken because it doesn't provide exactly the solution that they think will fix their problem often came to the absolute statement(s) incorrectly.

    And you might note that just because threads can be useful it does not negate the possibility that a non-threaded solution might not only be as good but might be substantially faster.
    Yes, I see that this would work, provided that the whole application, all classes and libraries and plugins and whatnot pre-allocated their memory. But how practical is that? Is it even possible?
    Your first statement is incorrect. It does not require any of that.

    Again it is matter of understanding your application.

    For example if my application requires a very large cache that doesn't mean that I must expect that logging debug statements (another part of the application) is going to also require a large amount of memory. Nor will logging even require a substantial amount. So if I limit the cache memory to a size that is less than the "remaining" memory then the application will in fact work and will still be able to have a very large cache.
    I know it looks like I'm just venting my frustration, and I am, but I came here in the hope that there is an answer, some technique I haven't heard of that helps keep the OOME in check. Sorry if I'm wasting your time.
    Which is my point. You are not asking for a solution. You have decided that there is only one possible solution which requires a specific feature and then you have decided that since java doesn't support that feature that the problem is unsolvable.
  • 33. Re: How to catch OutOfMemoryError?
    jschellSomeoneStoleMyAlias Expert
    Currently Being Moderated
    No, it would actually work but it requires that the whole application be instrumented in this way at each place an object is created, which is impractical for any number of reasons
    You are in fact wrong.

    It is not necessary that the whole application does it.

    Again if you know what your application is doing then you do in fact know what it is doing. I don't need to save space for reading the configuration file on the start up of the application even though it does in fact use memory. I do however need to reserve space when I attempt to build a tree which has 20 million nodes.
    The handler could have a few KB or MB around just for the occation, free them as the first step
    And what if I have a cache and which takes up 500 meg of memory? What happens if I empty it before attempting the call again?
  • 34. Re: How to catch OutOfMemoryError?
    jschellSomeoneStoleMyAlias Expert
    Currently Being Moderated
    Oh, I misinterpreted his remarks. Sorry. The fact is, though, that I have valid reasons to use threads.
    What you said is "Not using threads is not an option."

    That is an absolute.

    Your application very well might require threads. But I have certainly seen the claim made before that a threaded solution is required and is faster when in fact a non-threaded solution is substantially faster. I have also seen solutions where the bottleneck was the threads themselves, simply reducing them speeds up the application.

    But the statement is still along the lines of demanding that only one solution exists rather than presenting a problem and asking for alternatives.
  • 35. Re: How to catch OutOfMemoryError?
    807592 Newbie
    Currently Being Moderated
    And you might note that just because threads can be useful it does not negate the possibility that a non-threaded solution might not only be as good but might be substantially faster.
    Your application very well might require threads. But I have certainly seen the claim made before that a threaded solution is required and is faster when in fact a non-threaded solution is substantially faster. I have also seen solutions where the bottleneck was the threads themselves, simply reducing them speeds up the application.
    Of course you are right. I use threads for basically two things: simultaneous handling of incoming requests (like a web server) that are then forwarded to a cluster of servers, and simultaneous processing of data, where I carefully tune the number of threads in relation to the number of available cores to get the maximum measured performance. I am also playing with the idea of implementing a multi-threaded sort, because a significant part of the time is spent using one single core (out of eight available) to sort data, but I am skeptical, mainly because I think memory speed would be a bottleneck. It works in the parallel processing of data because I have a lot of processing on each piece of data, so the L-caches do help, but a sort would not benefit from that.
    For example if my application requires a very large cache that doesn't mean that I must expect that logging debug statements (another part of the application) is going to also require a large amount of memory. Nor will logging even require a substantial amount. So if I limit the cache memory to a size that is less than the "remaining" memory then the application will in fact work and will still be able to have a very large cache.
    Again if you know what your application is doing then you do in fact know what it is doing. I don't need to save space for reading the configuration file on the start up of the application even though it does in fact use memory. I do however need to reserve space when I attempt to build a tree which has 20 million nodes.
    Correct on both accounts. But what do I do if I can't know in advance how many nodes there will be, and if there are two such trees growing in different threads? I know, you will challenge the need to have them in different threads, and I promise I will think about this.

    I admit that I came with a preconceived solution that I knew doesn't exist in Java. I had a faint hope, however, that another solution would exist. And so far, even when your common-sense solutions would solve the problem under specific circumstances, I remain unconvinced that they are practical in multi-threaded and dynamic applications. Anyway, you gave me food for thought, and I thank you for that.
  • 36. Re: How to catch OutOfMemoryError?
    jschellSomeoneStoleMyAlias Expert
    Currently Being Moderated
    Correct on both accounts. But what do I do if I can't know in advance how many nodes there will be, and if there are two such trees growing in different threads? I know, you will challenge the need to have them in different threads, and I promise I will think about this.
    ...
    I remain unconvinced that they are practical in multi-threaded and dynamic applications
    Again you must know your application.

    If you have two trees that must exist at the same time and there was a memory problem then there is no solution. You must exit because both must exist and there is not enough memory. Period. Again no other solution exists. Even if you had a resume feature, it would still fail because building the trees themselves take too much memory.

    In my very real application I build a new cache in memory while the application continues to use the old cache. If the new cache fails to build then the application continues to use the old cache. If the new cache succeeds then it gets switched so the application is now using the new cache. And the old cache can be disposed of via the GC. And yes it gets built in a different thread. And the application is using a number of configurable threads which process transactions.

    And it is a product that is on the market and has a continous up time of 5 months now (when the first unit went live.) So my take is that it is very possible in "multi-threaded and dynamic applications".

    But I understand how the application works.
  • 37. Re: How to catch OutOfMemoryError?
    807592 Newbie
    Currently Being Moderated
    In my very real application I build a new cache in memory while the application continues to use the old cache. If the new cache fails to build then the application continues to use the old cache. If the new cache succeeds then it gets switched so the application is now using the new cache. And the old cache can be disposed of via the GC. And yes it gets built in a different thread. And the application is using a number of configurable threads which process transactions.
    How does a cache fail to build? Is it because of an OOME? In that case, how do you catch it? You don't have each possible memory consuming line of code wrapped in a try/catch block, since you said that was not necessary.
  • 38. Re: How to catch OutOfMemoryError?
    807592 Newbie
    Currently Being Moderated
    Let's end this discussion with the Java API:
    *Java 1.5 API - Error*:
    An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions. The ThreadDeath error, though a "normal" condition, is also a subclass of Error because most applications should not try to catch it.

    A method is not required to declare in its throws clause any subclasses of Error that might be thrown during the execution of the method but not caught, since these errors are abnormal conditions that should never occur.
    The discussion doesn�t end there.
    Because there are cases where catching an OOME does make sense:

    http://www.onjava.com/pub/a/onjava/2001/08/22/optimization.html

    As another concrete example, there was that editor written in Java (I believe it was JEdit), that would catch OOME when the user was trying to open a file too large to handle. So the code catched the OOME, aborted the opening , and informed the user of the problem.
    Isn't that better than aborting the application altogether?
  • 39. Re: How to catch OutOfMemoryError?
    807592 Newbie
    Currently Being Moderated
    Not C, C++,
    With C++ there is a standard way of coping with out-of-memory conditions. The stuff around custom new operator and exception handling is standardized and described in e.g. the Stroustrup book.
  • 40. Re: How to catch OutOfMemoryError?
    807592 Newbie
    Currently Being Moderated
    jschell wrote:
    Correct on both accounts. But what do I do if I can't know in advance how many nodes there will be, and if there are two such trees growing in different threads? I know, you will challenge the need to have them in different threads, and I promise I will think about this.
    ...
    I remain unconvinced that they are practical in multi-threaded and dynamic applications
    Again you must know your application.

    If you have two trees that must exist at the same time and there was a memory problem then there is no solution. You must exit because both must exist and there is not enough memory. Period. Again no other solution exists. Even if you had a resume feature, it would still fail because building the trees themselves take too much memory.
    I have been thinking about this and about your insistence on knowing the application.

    What I don't know is the amount of memory each memory consuming thread needs at each time, because (lets stay with the tree example) I don't know how large each tree wants to become, because it either depends on external factors, or the code wants as large a tree as possible. That doesn't mean that I must exit if there is not enough memory for one of the trees; in many cases I can use a smaller tree and things will still work.

    One way would be to catch the OOME and retry with a smaller tree, but since the first line of code requesting unavailable memory can be almost anywhere, I would have to wrap every memory-requesting code in a try/catch block, at the highest level that can easily recover from it.

    Of course I would prefer to know in advance how large the tree can grow to prevent an OOME. Not knowing how much the rest of the system may need forces me to be very conservative and make a sub-optimal use of the hardware, and it doesn't really prevent the OOME. That's where you say "know your application".

    I don't know the numbers when I'm writing the code, or even when the program starts, so I can't pre-allocate or pre-restrict. It has to be self-restricting: every dynamic memory-consumer has to check the free memory before attempting to grab it and stop doing so if there's not enough or wait until there is.

    Now the problem becomes one of prioritization. If two parts of the code want memory, which one should get it? Sometimes I want one of them to have priority. So there has to be some central authority to which the memory requesters have to announce they are going to start grabbing memory, and the authority may grant or hold permission depending on who they are, or grant partial permission to each (X amount for you and Y amount for you).

    Seems complicated to fine tune, but it looks like a possible solution. It still needs instrumenting a lot of code, but not as much as catching the OOME since I'm never approaching the zero free memory situation, where almost anything can throw an OOME.

    It is also quite brittle, since any new code that grabs memory has to use this system and every programmer has to keep it in mind. Code reviews are not bullet-proof (especially under stress) and implementing a JUnit test for this condition seems difficult. Also, I don't control all of the memory-consuming code, a few libraries also grab memory dynamically, but there is probably a way to control that on a case by case basis.

    Hmmm. Looks like overkill to me, but I see no real alternative.
  • 41. Re: How to catch OutOfMemoryError?
    807592 Newbie
    Currently Being Moderated
    Well, one approach is to hold your tree with a SoftReference: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ref/SoftReference.html

    If you do this, and the VM is unable to allocate memory, it will clear the references and then try to allocate again. If this happens, your entire tree (or maybe both) gets garbage collected, and you have to start over. If one tree is more important than another, then reference it with a normal (strong) reference, and reference the disposable one with a soft reference.
  • 42. Re: How to catch OutOfMemoryError?
    807592 Newbie
    Currently Being Moderated
    jschell wrote:
    I don't agree with the idea though, because the only thing it would let you clean up are static references (unless your "freeMemory()" method had access to the entire heap of objects), so basically it would only be able to gain memory through freeing globally referenced objects
    Err... in terms of my example.

    Then that is incorrect.

    In the catch block you can do something like cleaning a large cache - that has nothing to do with 'static references'. And if you did that then running the task, presuming it wasn't filling the cache in the first place, would then work.
    Dude I was never talking about your example. I think we've established the fact that catching an OOME and what jhand was suggesting were two completely different things.

    In your example, you catch the Error, do something to recover, and resume; however, your program control stack is disrupted by the very fact that the error was thrown.

    In jhand's example, you would basically supply your own implementation of a "free memory" code block to be executed regardless of where the instruction pointer is in your code; hence, it would have no knowledge of the program stack; hence, it would only be able to deal with the most global of resources.

    What you were suggesting is fine in my opinion. It was jhand's idea that I did not think would work.
  • 43. Re: How to catch OutOfMemoryError?
    807592 Newbie
    Currently Being Moderated
    karma-9 wrote:
    Let's end this discussion with the Java API:
    *Java 1.5 API - Error*:
    An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions. The ThreadDeath error, though a "normal" condition, is also a subclass of Error because most applications should not try to catch it.

    A method is not required to declare in its throws clause any subclasses of Error that might be thrown during the execution of the method but not caught, since these errors are abnormal conditions that should never occur.
    The discussion doesn�t end there.
    Because there are cases where catching an OOME does make sense:

    http://www.onjava.com/pub/a/onjava/2001/08/22/optimization.html

    As another concrete example, there was that editor written in Java (I believe it was JEdit), that would catch OOME when the user was trying to open a file too large to handle. So the code catched the OOME, aborted the opening , and informed the user of the problem.
    Isn't that better than aborting the application altogether?
    Yes, of course. Would you have been satisfied if I had also bolded the word "most" in "most such errors"? There are obviously exceptions. What I'm trying to say is that the end user could be a dick and specify his app to run with like 2 KB of memory. If he's going to do that, then inevitably your code is going to throw an OOME, and it isn't going to be any worse to abort the program than to try and make do with 2 KB of heap space.

    What you're saying about JEdit is completely understandable, and goes back to what jschell was saying before about knowing your program, which I absolutely agree with. If you are about to do some insanely memory-intensive thing that you can gracefully abort if you lack the resources, by all means, catch the OOME.
  • 44. Re: How to catch OutOfMemoryError?
    807592 Newbie
    Currently Being Moderated
    endasil wrote:
    Yes, of course. Would you have been satisfied if I had also bolded the word "most" in "most such errors"?
    Not really. Because I was actually disputing the already in bold "+a reasonable application should not try to catch+." statement from Sun, that you were quoting.

    And I mentioned JEdit as an example of an application that actually catches OOMEs and seems pretty "reasonable".

    Going a bit further, The way JEdit handles OOME is by no means an exception. Most applications I worked with could not afford being shutdown simply because Errors were thrown. So they would always try to recover from those.

    So, yes, I would dispute the quote even if "most" was bolded.