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
  • 45. Re: How to catch OutOfMemoryError?
    807592 Newbie
    Currently Being Moderated
    endasil wrote:
    karma-9 wrote:
    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.
    I think we are having two different discussions here. The JEdit is a perfect example of the first one. In this case, the program is exclusively dedicated to loading one file. In my opinion, catching a OOME is the wrong way to do it, although it would work. Just check the file size before you load it. There's nothing else in your program that will grab the memory from under your feet once you started loading the file. Even if there are some threads monitoring user events or timeouts, none of them will suddenly glob a huge amount of memory and, by knowing your program, you can factor that in when checking to see if the file will fit in memory. The Java API recommendation applies perfectly to this kind of situation.

    The second discussion, however, is about the exceptions to the Java API recommendation. We're dealing with several threads that are trying to open different files at the same time. And there are other threads running that, while not trying to grab large amounts of memory, are nonetheless creating one or two small objects here and there.

    If the memory grabbers manage to use up all but a few bytes of memory and an unsuspecting secondary thread tries to create its humble object, an OOME will hit the poor thread in the head and kill it. Adding a try/catch around the file-opening code will not catch all OOMEs. Increasing the -Xms and -Xmx values doesn't help either because the next day the files may be larger.

    If each memory grabber calls getFreeMemory() before it starts grabbing memory, it may be deceiving itself because the memory may be being grabbed by someone else at the same time. Counting the number of memory grabbing threads alive at the time and dividing the memory among them could be one solution, except that the first ones would get it all and the latecomers would get nothing. Setting a limit to the number of threads and giving each one 1/N of memory would artificially cripple the system most of the time. Checking free memory and pre-allocating in one atomic operation requires some weird memory managing techniques that I could write in C++ but not in Java (allocating a large byte array and then using that same block of memory for other objects).

    I don't see how knowing your program, as obvious and common-sensical as that is, can do anything to prevent this. You may account for all the memory your static parts will use, but as soon as you have more than one simultaneous dynamical growth, you're in my world.

    I humbly accept that I might be missing something big here, as jschell clearly disagrees with me and seems to have dealt with this situation successfully.
  • 46. Re: How to catch OutOfMemoryError?
    807592 Newbie
    Currently Being Moderated
    kdgregory wrote:
    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.
    That is an interesting approach, and I hate to follow every sentence with a "but"... but this is an all or nothing approach: either I get to have my tree or I loose it entirely. I'm not sure how the code would have to be written to deal with disappearing data, but that is a problem of me getting educated. ;)
  • 47. Re: How to catch OutOfMemoryError?
    jschellSomeoneStoleMyAlias Expert
    Currently Being Moderated
    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.
    Errr... because in the process that builds the cache there is a try catch block close to the top (actually there are several of them sequentially because there are optional processes that can fail and still continue if the main one worked.)
  • 48. Re: How to catch OutOfMemoryError?
    jschellSomeoneStoleMyAlias Expert
    Currently Being Moderated
    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.
    That of course makes no sense. You certainly don't build the tree everywhere.

    So there are two failure situations
    1. Building the tree fails
    2. The tree consumes almost all of the memory and subsequent operations fail because of that.

    Solutions.
    1. Catch the exception in the code that builds the tree. Discard any products that were built.
    2. Modify the tree building code such that it can not consume almost all of the memory.
    Not knowing how much the rest of the system may need forces me to be very conservative
    There are two possible answers to that.
    1. Not much
    2. A real lot because operation X requires it.

    For 2 that means that you know what X is, again know your application. And then you apply a strategy for that as well as the tree.
    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
    That is an absolute statement again.

    Why can't you know it? Provide a configuration value that says there can only be 1000 tree nodes. If you are building a tree an the total node count exceeds that then abort the build.
    It is also quite brittle...
    Perhaps, but since none of what you suggested sounds like anything that I would do nor would I recommend to anyone that they would even need I don't see a need to discuss it.
    Hmmm. Looks like overkill to me, but I see no real alternative.
    Looks to me like you don't actually understand the application or perhaps you don't have a real good grasp on how java manages memory and objects. Or perhaps both.
  • 49. Re: How to catch OutOfMemoryError?
    jschellSomeoneStoleMyAlias Expert
    Currently Being Moderated
    I think we are having two different discussions here. The JEdit is a perfect example of the first one. In this case, the program is exclusively dedicated to loading one file. In my opinion, catching a OOME is the wrong way to do it, although it would work. Just check the file size before you load it. There's nothing else in your program that will grab the memory from under your feet once you started loading the file.
    This suggests to me that you really need to learn a bit more about what is actually going on.

    Consider - what happens in the Java API to load the file?
    Consider - what is the GUI doing (in a separate thread) while the file is being loaded?
    Setting a limit to the number of threads and giving each one 1/N of memory would artificially cripple the system most of the time.
    Is this actually your problem or are you spinning off theoretical problems?

    One solution in a case like this is to limit the duration to which one thing can hold onto it. After that expires if there are more users then it can be divided futher.

    Alternatively in terms of a tree model eash node could be virtual and us a last used strategy to discard nodes when more users exist to balance the load.

    Or just simply limit the maximum number of concurrent users.

    There are very likely others. And the correct solution depends on knowing the application.
  • 50. Re: How to catch OutOfMemoryError?
    jschellSomeoneStoleMyAlias Expert
    Currently Being Moderated
    That is an interesting approach, and I hate to follow every sentence with a "but"... but this is an all or nothing approach: either I get to have my tree or I loose it entirely.
    ...but, what if you use SoftReference for nodes in the tree rather than the entire tree?
    ...but, what if you use SoftReference for data contained in the nodes?
  • 51. Re: How to catch OutOfMemoryError?
    807592 Newbie
    Currently Being Moderated
    jschell wrote:
    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.
    That of course makes no sense. You certainly don't build the tree everywhere.
    Aha! Here we identified the core of our disagreement. Apparently you think that the OOME can only be thrown by the code building the tree.

    Imagine we run two threads for one minute, with 1000 KB of available memory.
    Thread "treebuilder" creates 1000 1KB objects well before the minute ends.
    Thread "innocent_bystander" creates one 1KB object right at the end of the minute.

    Do we agree that the OOME will be thrown in the "innocent_bystander" thread?

    Here the innocent_bystander may be any thread (including main) in the system, performing any operation that may result in any memory request, for example the creation of an Integer for boxing an int during a method call.

    Wrapping the treebuilder in a try/catch block will not catch the OOME.

    You will argue the treebuilder should not create 1000 objects filling up the memory, but what happens if we have two treebuilder threads, each one trying to create 500 objects? No treebuilder is trying to use all the memory.
  • 52. Re: How to catch OutOfMemoryError?
    807592 Newbie
    Currently Being Moderated
    jschell wrote:
    I think we are having two different discussions here. The JEdit is a perfect example of the first one. In this case, the program is exclusively dedicated to loading one file. In my opinion, catching a OOME is the wrong way to do it, although it would work. Just check the file size before you load it. There's nothing else in your program that will grab the memory from under your feet once you started loading the file.
    This suggests to me that you really need to learn a bit more about what is actually going on.
    Well, you certainly choose what to leave out, don't you?
    jhandl wrote:
    Even if there are some threads monitoring user events or timeouts, none of them will suddenly glob a huge amount of memory and, by knowing your program, you can factor that in when checking to see if the file will fit in memory.
    Setting a limit to the number of threads and giving each one 1/N of memory would artificially cripple the system most of the time.
    One solution in a case like this is to limit the duration to which one thing can hold onto it. After that expires if there are more users then it can be divided futher.
    Alternatively in terms of a tree model eash node could be virtual and us a last used strategy to discard nodes when more users exist to balance the load.
    Or just simply limit the maximum number of concurrent users.
    There are very likely others. And the correct solution depends on knowing the application.
    Ok, I'll look into these suggestions.
  • 53. Re: How to catch OutOfMemoryError?
    jschellSomeoneStoleMyAlias Expert
    Currently Being Moderated
    Aha! Here we identified the core of our disagreement. Apparently you think that the OOME can only be thrown by the code building the tree.
    You are wrong.

    And I pointed this out quite a while ago. That situation only can occur if you are consuming all available memory and not planning ahead.

    I already pointed out that my current and past applications have built large caches in running multi-threaded applications and I never had a concern that there would be any out of memory errors, either in the builder thread nor in the non-builder threads.

    Because I know how the application works.
    Do we agree that the OOME will be thrown in the "innocent_bystander" thread?
    What we disagree on is that I understand how my applications behave and how memory is used in the application. And so your suggested scenario can NOT happen in my applications.

    They can't happen because I understand how my applications work.
  • 54. Re: How to catch OutOfMemoryError?
    jschellSomeoneStoleMyAlias Expert
    Currently Being Moderated
    Well, you certainly choose what to leave out, don't you?
    You mean because I haven't choosen to write an entire book, or at least several chapters to describe to you how memory management in virtual machines works, how applications flows work in general and how one might deal with a multitude of significantly different idioms that might be required to deal with specific situations?

    If so then yes you are correct I have not done that.

    But then you didn't actually come here looking for a solution either but merely came to condemn java because it didn't have a feature which you were sure would fix your problem (and I am rather certain wouldn't.)

    And as far as I can tell you still haven't provide sufficient detail to really lead to any specific solution and you don't actually seem to understand how much memory will actually be used by your app outside of the builders. I can't help you with any of that.
  • 55. Re: How to catch OutOfMemoryError?
    807592 Newbie
    Currently Being Moderated
    But then you didn't actually come here looking for a solution either but merely came to condemn java because it didn't have a feature which you were sure would fix your problem (and I am rather certain wouldn't.)
    I don't know why you keep taking the time to post here if you already decided I am a troll. I am doing a great deal of an effort not to respond to your constant insults, because I did come here for help and you are spending your time trying to help. I already confessed to coming with a preconceived idea of how it should work knowing it doesn't and I humbly accepted I could be wrong about anything, especially since you said that you wrote a similar application and had not had this problem. So please, please stop being so patronizing.
    And as far as I can tell you still haven't provide sufficient detail to really lead to any specific solution and you don't actually seem to understand how much memory will actually be used by your app outside of the builders. I can't help you with any of that.
    Here, once again, is a cue: you say "builders". Yes, there has to be more than one builder or otherwise this would be trivial. In my case, there are many builders, and they may be running at the same time. The problem is how to make sure they don't collectively consume all the available memory.

    The trivial solution is to put a cap on both the number of builders and the amount of memory each one can consume. This is, I think, what you are suggesting. The problem with that, as I said previously, is that it would artificially cripple the application: if I put a low cap on the number of simultaneous users, the application stops being useful except maybe as a toy. If I allow many threads then each one can only use a tiny fraction of the memory, and so the application would slow down to a crawl as everything would be disk-based. And most of the time the memory would be almost completely unused, since most of the time there are not that many simultaneous users, so the system would behave under normal circumstances as if it was being constantly slashdotted.

    So far I think there are two possible solutions, the first one horrible enough that it could only have come from me, and the one kdgregory suggested, which I discarded at the beginning but that seems more plausible now that I had more time to think about it:

    1. To have a memory manager that grants more or less memory depending on the current situation, and that could even send feedback to current threads so they free some memory or grab more.

    2. Use hard references for minimalist data structures and soft references from there on, so they get GCed as needed.

    I consider the question answered (and the subject beaten to death), so I don't expect any more responses. Thanks to all who chimed in with a suggestion!
  • 56. Re: How to catch OutOfMemoryError?
    DrClap Expert
    Currently Being Moderated
    Well, yeah. SoftReferences are the answer to your question. I don't understand why this thread went on as long as it did. I mean, SoftReference was put into the language specifically so that the garbage collector could manage memory (which is its job) instead of the user having to manage memory (which is the garbage collector's job). So somebody should have mentioned them before reply #37.
  • 57. Re: How to catch OutOfMemoryError?
    807592 Newbie
    Currently Being Moderated
    DrClap wrote:
    Well, yeah. SoftReferences are the answer to your question. I don't understand why this thread went on as long as it did. I mean, SoftReference was put into the language specifically so that the garbage collector could manage memory (which is its job) instead of the user having to manage memory (which is the garbage collector's job). So somebody should have mentioned them before reply #37.
    Yes, and now I'm going to bury myself in TFM to learn about the SoftReferences, WeakReferences and PhantomReferences and their uses.
1 2 3 4 Previous Next