java.lang.OutOfMemoryError, when is memory reclaimed? - java

Once this exception is thrown, is object that caused this thrown out of memory? Does it happen right away?
In other words, if i am adding objects to a list, at some point this can no longer happen and OOM error is thrown. At that time, does anything happen to the list itself?
java.lang.OutOfMemoryError: Java heap space

This is thrown when a new object could not be created. The current object will continue to exist.
However, due to the nature of an error like this the current code will stop executing and it's likely that the current object will be garbage-collected soon. It just depends on the structure of your code and whether references are still being held to your object.

From documentation:
Thrown when the Java Virtual Machine cannot allocate an object because it is out of memory, and no more memory could be made available by the garbage collector.

According to http://docs.oracle.com/javase/6/docs/api/, an OutOfMemoryError is:
Thrown when the Java Virtual Machine cannot allocate an object because
it is out of memory, and no more memory could be made available by the
garbage collector.
So it happens as soon as the JVM sees that it does not have enough heapspace to allocate memory for the new object you're trying to create. So the object never gets created because you don't have enough memory.

Related

What will happen if java didn't collect garbage?

My question is very very clear .. if it didn't collect garbage what will happen
And why that thing does not happen in c++
If stale objects are not collected, you will run into an OutOfMemoryError. And this will also happen in C++, if you don't clean up old data (the error is probably not called OutOfMemoryError, but the consequences are the same i guess).
It does happen in C/C++. In a different way. In C/C++ the responsibility lies more with the programmer to keep track of memory allocated and to free it. Programmers have direct access to memory in the form of pointers. In java it is all hidden from programmer. You don't need to keep track of memory, JVM does it for you in the form of garbage collection. That does not mean you can allocate memory to objects wily-nily. Global objects are retained for long time and if GC cannot reach them in time, the memory goes beyond limit and OutOfMemoryException happens.

Is Java GC run when I'm out of memory?

I'm developing an Android-based 3D game in Java (not using the NDK).
One of the must-haves for any game is a resource cache, in which I can store loaded textures, meshes, sounds, etc.
My plan is to develop a resource cache that hands out weak references to certain resources, so that only the cache itself keeps a strong reference to the resource, meaning that if I remove a resource from my cache, it will be garbage collected without me having to worry about it.
I'm having a hard time finding an answer to the following question though:
Say I have filled my resource cache to the point where my heap space is almost completely full. I now want to load an additional resource, but its memory footprint is so large that it won't fit in my available heap space.
To accommodate for the new object's size, I remove some entries from my cache and I load in the new object. Will this possibly cause an OutOfMemory exception?
As long as the garbage collector hasn't sweeped through my recently removed objects, the memory stays in use, so is the garbage collector smart enough to run a new sweep in order to accommodate the newly allocated object?
The JVM will run a Full GC before throwing an OutOfMemoryError (it doesn't want to throw OOME, so it'll attempt everything possible). It's just that considerate.
GC is not guaranteed to run, although it usually does. I know I've seen OOME without GC and GC could have made a difference but it's rare. Usually if you've dereferenced objects and they are eligible for GC, then when you need memory allocated for new objects the JVM will do its job great and you will be fine. Properly dereferencing objects is usually the problem if you get an OOME and you think enough memory should be available.
See this post:
Is the garbage collector guaranteed to run before Out of Memory Error?
Also you can request GC, but that also does not guarantee that it will be run, and it may not be a good idea. See this post:
Garbage collector in Android
The [Java Machine specification states(#6.3)] states this:
OutOfMemoryError: The Java Virtual Machine implementation has run out of either virtual
or physical memory, and the **automatic storage manager was unable to reclaim enough memory**
to satisfy an object creation request.
So JVM does guarantee that it will try what it can to free up memory through GC before it throws an OutOfMemoryError.
To accommodate for the new object's size, I remove some entries from my cache and I load in the new object. Will this possibly cause an OutOfMemory exception? As long as the garbage collector hasn't sweeped through my recently removed objects, the memory stays in use, so is the garbage collector smart enough to run a new sweep in order to accommodate the newly allocated object?
By remove I understand you set them to null to make them eligible for GC. Although you have set them to null, the GC might decide not to do a memory sweep at all. Now you could explicitly call System.gc but then again the GC will be running in a separate low-priority thread. And collection of Objects will not be immediate. Now, once you try to load the large resource, the GC finds out that the memory is less, it starts its task to free as much memory as possible. But it will still throw OutOfMemory because you don't have memory when trying to load your resource.
I just found out the answer to my own question in accordance with what Kayaman said earlier:
The Java Virtual Machine implementation has run out of either virtual or physical memory, and the automatic storage manager was unable to reclaim enough memory to satisfy an object creation request.
Found at http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.3

Java size of an Exception in memory

Does anyone know how much memory an Exception occupies once it is created and thrown?
For example, NullPointerException.
And how exceptions are being garbage collected?
Does anyone know how much memory an Exception occupies once it is created and thrown?
That would depend entirely on the exception. Like any other object, it contains variable amount of data; the String message could be 4MB if someone did something silly:
Exception e =
new Exception(new String("Some gigantic message ... lalalalalalalalla"));
(Edit: ok, this is somewhat misleading; the exception contains a reference to a String and reference values are a fixed size, but the String itself might only be referenced by the exception - I changed it to be a non-literal to explicitly show it could be something that is collectible. A custom exception could hold anything though, it's an object like any other. In addition, it depends how far it has been thrown, since it holds the stack trace inside of it. There's a good Q/A here on SO; In java, what is the best way to determine the size of an object that covers this. )
And how exceptions are being garbage collected?
Just as any other object is. The Exception is thrown up the call stack and one of two things happen:
1) You catch it, and it's assigned to a variable in the catch block:
catch (Exception e) {
e now holds the one and only reference to the exception. When no more references to it exist (i.e. it either falls out of scope at the bottom of the catch block, or the object you pass it to gets collected, etc), it will get collected.
2) You don't catch it and it hits the top of the call stack for the current thread. At that point the exception falls out of scope so it will be collected, and the thread is of course halted.
** To be completely pedantic when I say "will get collected" I mean eventually as when an object in Java has no more references to it it's it's eligible for collection, and the GC deals with it.
Java Exceptions are Object so as any Other Objects the size depends by it structure if you have created a custom exception you can (for example) store e complete binary file other Object until you have free memory.
You can set the initial and maximum space for your application.
The free space change dynamically and now there is the GC question.
Java Exceptions are Object so as any Other Objects garbage collection uses the rules in your Enviorment.
For a quick reference about exceptions http://docs.oracle.com/javase/tutorial/essential/exceptions/
this is an article about garbage collection where the key concept are
Summary on Garbage collection in Java
1) Java Heap is divided into three generation for sake of garbage collection. These are young generation, tenured or old generation and Perm area.
2) New objects are created into young generation and subsequently moved to old generation.
3) String pool is created in Perm area of Heap, garbage collection can occur in perm space but depends upon JVM to JVM.
4) Minor garbage collection is used to move object from Eden space to Survivor 1 and Survivor 2 space and Major collection is used to move object from young to tenured generation.
5) Whenever Major garbage collection occurs application threads stops during that period which will reduce application’s performance and throughput.
6) There are few performance improvement has been applied in garbage collection in java 6 and we usually use JRE 1.6.20 for running our application.
7) JVM command line options –Xmx and -Xms is used to setup starting and max size for Java Heap. Ideal ratio of this parameter is either 1:1 or 1:1.5 based upon my experience for example you can have either both –Xmx and –Xms as 1GB or –Xms 1.2 GB and 1.8 GB.
8) There is no manual way of doing garbage collection in Java.
Read more: http://javarevisited.blogspot.it/2011/04/garbage-collection-in-java.html
If you use java 7 an intersting question about GC is this
Java 7 (JDK 7) garbage collection and documentation on G1
Other suggestion are useful if you need to view only the state bat if you need to tune the config of your app you need to work with GC alg end memory.
I'm wondering why nobody mentioned that the first thing which happens when you create an exception is that the stack trace is populated:
public Throwable() {
fillInStackTrace();
}
If you create your own Exception class and override the fillInStackTrace() method to do nothing, your Exception will become just a simple Java Object and will occupy just as much memory as other objects (which have the same fields/values). But of course you will lose the most precious thing: the stack trace. As a conclusion, most of the memory occupied by the Exception object is due to storing the stack trace (it is stored in an internal format, then converted to StackTraceElement[] when the getStackTrace() method is called). So the larger the stack trace, the more memory the exception will occupy.
public class LightWeightException extends RuntimeException {
public LightWeightException(String message) {
super(message);
}
#Override
public synchronized Throwable fillInStackTrace() {
return this;
}
}
Thats easy to find out by yourself. Launch jvisualvm and attach to the application you want to profile.
Switch to the memory tab and filter for the exception you are looking for.
That should give you a good picture of how many bytes are used by exception objects - and also how this relates to your total heap size - and how well and how often they get collected.
Use Java Mission Control for checking this.

Behaviour of JVM during out of memory error? List s = new ArrayList<String>();

try {
for(;;) {
s.add("Pradeep");
}
} finally {
System.out.println("In Finally");
}
In the try block the jvm runs out of memory,then how is jvm excuting finally block when it has no memory?
Output:
In Finally
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
Presumably the System.out.println call requires less memory than the s.add("Pradeep") call.
If s is an ArrayList for instance, the s.add call may cause the list to attempt to double up it's capacity. This is possibly a quite memory demanding operation, thus it is not very surprising that the JVM can continue executing even if it can't perform such relatively expensive task.
Here is more simple code that demonstrated better what happens:
try {
int[] a = new int[Integer.MAX_VALUE];
} catch( Exception e ) {
e.printStackTrace();
}
The allocation of the array fails but that doesn't mean Java has no free memory anymore. If you add items to a list, the list grows in jumps. At one time, the list will need more than half of the memory of the VM (about 64MB by default). The next add will try to allocate an array that is too big.
But that means the VM still has about 30MB unused heap left for other tasks.
If you want to get the VM into trouble, use a LinkedList because it grows linearly. When the last allocation fails, there will be only very little memory to handle the exception:
LinkedList<Integer> list = new LinkedList<Integer>();
try {
for(;;) {
list.add(0);
}
} catch( Exception e ) {
e.printStackTrace();
}
That program takes longer to terminate but it still terminates with an error. Maybe Java sets aside part of the heap for error handling or error handling doesn't need to allocate memory (allocation happens before the code is executed).
In the try block the jvm runs out of memory, then how is jvm excuting finally block when it has no memory?
The JVM "runs out of memory" and throws an OOME when an attempt to allocate an object or array fails because there is not enough space available for that object. That doesn't mean that everything has to stop instantly:
The JVM can happily keep doing things that don't entail creating any new objects. I'm pretty sure that this is what happens in this case. (The String literal already exists, and implementation of the println method is most likely copying characters into a Buffer that was previously allocated.)
The JVM could potentially allocate objects that are smaller than the one that triggered the OOME.
The propagation of the OOME may cause variables containing object references to go out of scope, and the objects that they refer to may then become unreachable. A subsequent new may then trigger the GC that reclaims said objects, making space for new ones.
Note: the JLS does not specify that the String object that represents that literal must be created when the class is loaded. However, it certainly says that it may be created at class load time ... and that is what happens in any decent JVM.
Another answer said this:
Maybe Java sets aside part of the heap for error handling or error handling doesn't need to allocate memory (allocation happens before the code is executed).
I think this is right. However, I think that this special heap region is only used while instantiating the OOME exception, and filling in the stack trace information. Once that has happened, the JVM goes back to using the regular heap. (It would be easy to get some evidence for this. Just retry the add call in the finally block. If it succeeds, that is evidence that something has made more memory available for general use.)
The JVM isn't really out of memory and unable to proceed. This error says that it failed to allocate memory and so it didn't. That might mean its very low. But here what failed was resizing the collection's internal array which is huge. There's a lot of memory left just not that much to double a large array. So it can proceed just fine with finally.
The error is thrown when the heap space exceeds that set by the -Xmx flag, and it cannot continue as normal. The error propagates, but it does not immediately cause the JVM to be shutdown (of the system exited in such cases, there would be no point in the OOM error, as it could never be thrown).
As the JVM has not exited it will try to, as according to the language spec, execute the finally block.
Finally executes almost always.
When the exception was thrown, the JVM collected as much as memory as possible, which, reading your code, probably meant that it collected the whole s collection.
When the finally is reached, it only has to create a new string "In finally" in the string pool no additional memory is required, and it has no problems since it has freed up space before.
Try printing s.size() on the finally, you'll see how it is not able to do it. (EDIT: if in catch, finally or after the try block, there´s a line of code using the s collection, the Garbage Collector is unable to collect it at the moment the OOME is thrown. This is why the heap memory will be almost full, so any new object allocation may throw another OOME again. It is difficult to predict without seeing the complete code).

When does Java's garbage collection free a memory allocation?

I have created an object in Java, Named FOO. FOO contains a large amount of data.. I don't know say for a ten mega byte text file that I have pulled into ram for manipulation.(This is just an example)
This is clearly a huge amount of space and I want to deallocate it from memory. I set FOO to NULL.
Will this free up that space in memory automatically?
or
Will the memory taken by the loaded text file be around until automatic garbage collection?
When you set the reference of any object to null, it becomes available for garbage collection. It still occupies the memory until the garbage collector actually runs. There are no guarantees regarding when GC will run except that it will definitely run and reclaim memory from unreachable objects before an OutOfMemoryException is thrown.
You can call System.gc() to request garbage collection, however, that's what it is - a request. It is upto GC's discretion to run.
Using a WeakReference can help in some cases. See this article by Brian Goetz.
Actually the object is not named FOO. FOO is the name of a variable which is not the object; the variable contains a reference to the object. There could be several distinct variables containing references to the same object.
The garbage collector works by automatically detecting unreachable objects: these are objects which the application cannot use anymore because it has irretrievably forgotten where they are (the application may possibly access any object for which it has a reference to, including the references stored in field in objects it can access, and so on).
When you set FOO = null, assuming that FOO contained at that point the last reachable reference to the object, then the memory is released immediately, in the following sense: at the very clock cycle at which null is set in FOO, the object becomes unreachable. Therefore, the garbage collector will notice that unreachable object and reclaim the corresponding memory block; that is, the GC will do that the next time it can be bothered to run. Of course, the actual bits which constitute the object may linger a bit in memory; but that block is nonetheless "free" since the memory allocator will automatically run the GC when free memory is tight. From the application point of view, the object is as good as dead and the corresponding memory is free since that memory will be reused the next time the application needs it. The whole thing is automatic.
Things are a bit more complex with regards to the operating system. If an unreachable object is free memory from the application point of view, it is still, as far as the OS is concerned, a block of RAM dedicated to the running process. That block of RAM may be given back to the OS only when the GC (which is, at the OS level, a part of the process) actually runs, notices that the object is unreachable, and condescends to give the block back to the OS. When the GC runs heavily depends on the GC technology and how the application allocates objects; also, some GC will never give back the block the OS at all (the GC knows that the block it free, the memory allocator will reuse it at will, but not other processes).
System.gc() is a hint to the VM, so that it runs the GC now. Formally, it is only a hint, and the VM is free to ignore it. In practice, it runs the GC, unless the VM was instructed not to obey such commands (with Sun's JVM, this is a matter of a specific command-line flag). Even if the GC runs, it does not necessarily give back the memory to the operating system. System.gc() is not terribly useful.
Setting foo = null; does not mean that foo will be garbage collected immediately. Instead, it will be collected when the GC next runs, if it can be. When foo is collected, any objects for which it holds the sole reference will also be eligible for collection and therefore collected.
Note that even calling System.gc() does not guarantee that that JVM will do it right away.
System.gc() is just a request and there is no guarantee that it's effect immediately.
There's no guarantee that JVM will do it right away, you can try to force it by using System.gc()
The garbage collector will free the memory after you "destroy" the reference. i.3 Setting the object reference to null. You can use forced garbage collection option but you should use it with care. The Garbage collector is designed to use an optimized schedule so calling the System.gc() may ruin the rhythem and possibly have less performance due to unnecessary task switching.
Alternatively you can think about a way that allows you to not to load large amounts of data into memory. If you can gain that by improving your code that would be much better.

Categories

Resources