Java Memory Management
-
We have some third-party software that lets message objects accumulate in a huge
LinkedList
. How huge? They actually let it grow to fill up the heap and then catch theOutOfMemoryError
. Even ignoring the question of whether this is a good design decision, their error-handling method leaves something to be desired.if (throwable isinstance OutOfMemoryError)
{
System.gc();
throwable.printStackTrace();
// ...
}If you don't instantly see what's wrong with that, here are some hints:
- The JVM will always attempt a garbage collection before throwing an
OutOfMemoryError
. - Stack traces require string manipulation. Strings require memory...
- The JVM will always attempt a garbage collection before throwing an
-
We have some third-party software that lets message objects accumulate in a huge
LinkedList
. How huge? They actually let it grow to fill up the heap and then catch theOutOfMemoryError
. Even ignoring the question of whether this is a good design decision, their error-handling method leaves something to be desired.if (throwable isinstance OutOfMemoryError)
{
System.gc();
throwable.printStackTrace();
// ...
}If you don't instantly see what's wrong with that, here are some hints:
- The JVM will always attempt a garbage collection before throwing an
OutOfMemoryError
. - Stack traces require string manipulation. Strings require memory...
ClementsDan wrote:
If you don't instantly see what's wrong with that, here are some hints: The JVM will always attempt a garbage collection before throwing an OutOfMemoryError. Stack traces require string manipulation. Strings require memory...
But is this documented (in the Java API) along side the System.gc(); call? If not it should be, and would prevent such superfluous calls.
WPF - Imagineers Wanted Follow your nose using DoubleAnimationUsingPath
- The JVM will always attempt a garbage collection before throwing an
-
We have some third-party software that lets message objects accumulate in a huge
LinkedList
. How huge? They actually let it grow to fill up the heap and then catch theOutOfMemoryError
. Even ignoring the question of whether this is a good design decision, their error-handling method leaves something to be desired.if (throwable isinstance OutOfMemoryError)
{
System.gc();
throwable.printStackTrace();
// ...
}If you don't instantly see what's wrong with that, here are some hints:
- The JVM will always attempt a garbage collection before throwing an
OutOfMemoryError
. - Stack traces require string manipulation. Strings require memory...
ClementsDan wrote:
The JVM will always attempt a garbage collection before throwing an OutOfMemoryError
Really? It does? Because the .NET garbage collector does not. (Tess' MSDN blog.)
- The JVM will always attempt a garbage collection before throwing an
-
We have some third-party software that lets message objects accumulate in a huge
LinkedList
. How huge? They actually let it grow to fill up the heap and then catch theOutOfMemoryError
. Even ignoring the question of whether this is a good design decision, their error-handling method leaves something to be desired.if (throwable isinstance OutOfMemoryError)
{
System.gc();
throwable.printStackTrace();
// ...
}If you don't instantly see what's wrong with that, here are some hints:
- The JVM will always attempt a garbage collection before throwing an
OutOfMemoryError
. - Stack traces require string manipulation. Strings require memory...
- The JVM will always attempt a garbage collection before throwing an
-
ClementsDan wrote:
The JVM will always attempt a garbage collection before throwing an OutOfMemoryError
Really? It does? Because the .NET garbage collector does not. (Tess' MSDN blog.)
Not true. See Maoni's blog at http://blogs.msdn.com/maoni/archive/2006/06/06/when-memory-is-running-low.aspx[^]. "If you don't have enough physical storage we will fail when we need to commit memory. We attempt a GC at this point and if afterwards there's still not enough physical storage to commit we will throw an OOM. "When you have a page file, physical storage includes both physical memory and the page file." -- from comment #3[^]. So the order goes: - application tries to allocate memory - existing heap VM segments are full - try to create new segment - cannot create a new segment (out of VA space or commit limit reached) - performs a GC to compact heap - if still not enough space available, fails with OutOfMemoryException.
DoEvents: Generating unexpected recursion since 1991
-
Not true. See Maoni's blog at http://blogs.msdn.com/maoni/archive/2006/06/06/when-memory-is-running-low.aspx[^]. "If you don't have enough physical storage we will fail when we need to commit memory. We attempt a GC at this point and if afterwards there's still not enough physical storage to commit we will throw an OOM. "When you have a page file, physical storage includes both physical memory and the page file." -- from comment #3[^]. So the order goes: - application tries to allocate memory - existing heap VM segments are full - try to create new segment - cannot create a new segment (out of VA space or commit limit reached) - performs a GC to compact heap - if still not enough space available, fails with OutOfMemoryException.
DoEvents: Generating unexpected recursion since 1991
From Tess' blog: "Virtual memory allocations are not necessarily (or very seldom) lined up nicely in memory. For example, dll’s have preferred loading addresses so gaps are left between them, and virtual allocations that have been de-allocated will also leave gaps. This means that even though you can address 2 GB of virtual memory you may not be able to use it all since when enough memory is used, the memory will look somewhat like a Swiss cheese and your plug might have a big enough hole to fit in. This is what happens when you get an OutOfMemory exception." It seems to me like what these two blogs are saying is conflicting, and I don't know which one to believe.
-
From Tess' blog: "Virtual memory allocations are not necessarily (or very seldom) lined up nicely in memory. For example, dll’s have preferred loading addresses so gaps are left between them, and virtual allocations that have been de-allocated will also leave gaps. This means that even though you can address 2 GB of virtual memory you may not be able to use it all since when enough memory is used, the memory will look somewhat like a Swiss cheese and your plug might have a big enough hole to fit in. This is what happens when you get an OutOfMemory exception." It seems to me like what these two blogs are saying is conflicting, and I don't know which one to believe.
actually they're both right. What Tess is saying is that even though the total free memory you have may be in theory enough to satisfy the request, it may be fragmented into many free blocks. None of these free blocks is large enough to satisfy the request.
Silence is the voice of complicity. Strange women lying in ponds distributing swords is no basis for a system of government. -- monty python Might I suggest that the universe was always the size of the cosmos. It is just that at one point the cosmos was the size of a marble. -- Colin Angus Mackay
-
actually they're both right. What Tess is saying is that even though the total free memory you have may be in theory enough to satisfy the request, it may be fragmented into many free blocks. None of these free blocks is large enough to satisfy the request.
Silence is the voice of complicity. Strange women lying in ponds distributing swords is no basis for a system of government. -- monty python Might I suggest that the universe was always the size of the cosmos. It is just that at one point the cosmos was the size of a marble. -- Colin Angus Mackay
That is indeed what Tess is saying, but she also says "that is what happens when you get an OutOfMemoryException". The other party claims the garbage collector will perform defragmentation (which is part of garbage collection, after all) before throwing OutOfMemoryException, and if that is true you wouldn't get OOM as long as the new allocation requires less than total free memory. If so, the only time you should get the exception should be when the live objects are pinned. (Very large objects are said to be "pinned" because they are never moved in defragmentation due to the hard work it would be moving such big objects around.) I guess if you want very much to conclude that they both are right you could assume Tess was talking about pinned objects, but that is a rather contrived way of getting there, and I frankly don't see the point. For me the important thing isn't who is right but what the fact is. And that is unfortunately still no more clear for me.