This question already has answers here:
How to force garbage collection in Java?
(25 answers)
Closed 8 years ago.
How can I manually delete a specific object before the garbage collector would ever collect it ?
For example I want to delete requestToken object. How can I do that ?
The short answer is that you can't, and that you don't need to. The GC will reclaim the memory when it needs to ... and there is no reason to interfere with that.
The only situation I can think of for needing to delete an object sooner is when the object contains information that needs to be erased ... for information security reasons. (The classic example is when you are processing a password provided by the user and you are worried that it might leak via a code dump or something) In that case, you need to implement a method on your object for erasing the object's fields by overwriting them. But this requires careful design; e.g. to make sure that you find and erase all traces of the information.
It is also sometimes necessary to "help" the GC a bit to avoid potential memory leaks. A classic example of this is the ArrayList class, which uses a Java array to represent the list content. The array is often larger than the list's logical size, and the elements of the array could contain pointers to objects that have been removed from the list. The ArrayList class deals with this by assigning null to these elements.
Note that neither of these examples involve actually deleting objects. In both cases, the problem / issue is addressed another way.
It is also worth noting that calling System.gc() is usually a bad idea:
It is not guaranteed to do anything at all.
In most situations, it won't do anything that wouldn't happen anyway.
In most situations, it is inefficient. The JVM is in a better position than application code to know the ergonomically most efficient time to run the GC. (Read this for a first-principles explanation of the ergonomics.)
The only cases where running the GC in production code is advisable are when you are trying to manage GC pauses, and you know that a pause is acceptable at a particular point in time. (For example, when you are changing levels in an interactive game ... )
You cannot delete an object, you can just try to make it eligible for garbage collection in its next cycle. The best you could do is , set the object as null and try calling System.gc();
Note: System.gc() call will only request the JVM to run garbage collector but it cannot force it to.
Related
This question already has answers here:
Error java.lang.OutOfMemoryError: GC overhead limit exceeded
(22 answers)
Closed 6 months ago.
After a lot of effort I can't seem to overcome the problem of getting a
GC overhead limit exceeded
error in my Java program.
It occurs inside a large method that contains large string manipulation, many lists of objects and accesses to DB.
I have tried the following:
after the use of each ArrayList, I have added: list=new ArrayList<>(); list=null;
for the strings, instead of having e.g. 50 appends (str+="....") I try to have one append with the total text
after each DB access I close the statements and the resultSets.
This method is called from main like this:
for(int i=0; i<L; i++) {
cns = new Console(i);
cns.processData();//this is the method
cns=null;
}
When this loop gets executed 1 or 2 times, everything is ok. For L>=3 it's almost certain that I will get the garbage collector error.
Shouldn't the fact that I have a cns=null after each execution of the method, force the GC and free everything from the previous execution?
Should I also delete all private attributes of the object before setting it to null? Maybe putting a Thread.sleep() could force the GC after each loop?
There's actually no reason to set cns to null at the end of each loop. You're setting it to a new Console() at the beginning of the loop anyway - if anything could be freed by setting it to null, it's also going to be freed by setting it to a new object.
You can try a System.gc(); call to suggest the system do a garbage collection, but I don't know if that would help you or make it worse. The system IS already attempting garbage collection - if it wasn't, you wouldn't get this error.
You don't show us exactly how you're building your Strings, but keep in mind that += isn't the only culprit. If you have something like String s = "Hello " + "to the" + " world";, that's just as bad as putting that on three lines and using +=. If it's an issue, StringBuilder may be your friend.
You can read the answers at Error java.lang.OutOfMemoryError: GC overhead limit exceeded for some other suggestions on how to avoid this error. It seems that for some people it's triggered when you're almost, but not quite, out of memory. So increasing the amount of memory available to Java may (or may not) help.
Basically, an "GC overhead limit exceeded" is a symptom of having too much reachable data. The heap is filling up with things that cannot be garbage collected ... 'cos they are not garbage! The JVM is running the GC again and again in an attempt to make space. Eventually, it decides that too much time is being spent garbage collecting, and it gives up. This is usually the correct thing to do.
The following ideas from your question (and the other answer) are NOT solutions.
Forcing the GC to run by calling System.gc() won't help. The GC is already running too often.
Assigning null to cns won't help. It immediately gets something else assigned to it. Besides, there is no evidence that the Console object is occupying much memory.
(Note that the constructor for the java.io.Console class is not public, so your example is not meaningful as written. Perhaps you are actually calling System.getConsole()? Or perhaps this is a different Console class?)
Clearing private attributes of an object before setting it to null is unlikely to make any difference. If an object is not reachable, then the values of its attributes are irrelevant. The GC won't even look at them.
Calling Thread.sleep() will make no difference. The GC runs when it thinks it needs to.
The real problem is ... something that we can't determine from the evidence that you have provided. Why is there so much reachable data?
In general terms, the two most likely explanations are as follows:
Your application (or some library you are) is accumulating more and more objects in some data structure that is surviving beyond a single iteration of the for loop. In short, you have a memory leak.
To solve this, you need to find the storage leak; see How to find a Java Memory Leak. (The leak could be related to database connections, statements or resultsets not being closed, but I doubt it. The GC should find and close these resources if they have become unreachable.)
Your application simply needs more memory. For example, if a single call to processData needs more memory than is available, you will get an OOME no matter what you try to get the GC to do. It cannot delete reachable objects, and it obviously cannot find enough garbage to fast enough.
To solve this, first see if there are ways modify the program so that it needs less (reachable) memory, Here are a couple of ideas:
If you are building a huge string to represent the output before writing it to an OutputStream, Writer or similar. You would save memory if you wrote directly to the output sink.
In some cases, consider using StringBuilder rather than String concatenation when assembling large strings. Particularly when the concatenations are looped.
However, note that 1) in Java 8 and earlier javac already emits StringBuilder sequences for you for concatenation expressions, and 2) in Java 9+, javac emits invokedynamic code that is better than using StringBuilder; see
JDK 9/JEP 280: String Concatenations Will Never Be the Same
If that doesn't help, increase the JVM's heap size or split the problem into smaller problems. Some problems just need lots of memory to solve.
So what I am having here is a java program the manipulates a huge amount of data and store it into objects (Mainly hash-maps). At some point of the running time the data becomes useless and I need to discard so I can free up some memory.
My question is what would be the best behavior to discard these data to be garbage collected ?
I have tried the map.clear(), however this is not enough to clear the memory allocated by the map.
EDIT (To add alternatives I have tried)
I have also tried the system.gc() to force the garbage collector to run, however it did not help
HashMap#clear will throw all entries out of the HashMap, but it will not shrink it back to its initial capacity. That means you will have an empty backing array with (in your case, I guess) space for tens of thousands of entries.
If you do not intend to re-use the HashMap (with roughly the same amount of data), just throw away the whole HashMap instance (set it to null).
In addition to the above:
if the entries of the Map are still referenced by some other part of your system, they won't be garbage-collected even when they are removed from the Map (because they are needed elsewhere)
Garbage collections happens in the background, and only when it is required. So you may not immediately see a lot of memory being freed, and this may not be a problem.
system.gc()
is not recommended as jvm should be the only one to take care of all the garbage collection. Use Class WeakHashMap<K,V> in this case.
The objects will automatically be removed if the key is no longer valid
Please read this link for reference
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have written a small Java program where I create 10 String Objects.
Can someone explain or answer the following questions.
What are the best practices to create a Object. ie; When I create a Object should I also make sure I delete the object once its used. If, How do I delete it?
If I don't delete the object, is that the object will be lying until the program ends?
Is there a way to check the number of active objects when a program is running?
public class Test{
static public void main(String[] args){
for (Integer i = 0; i < 10; i ++){
String s1 = new String("Creating new String");
}
System.out.println("Program COmpleted");
}
}
When I create a Object should I also make sure I delete the object once its used.
No. You can not explicitly delete an Object in Java. For certain memory-intensive use cases, it might make sense to explicitly nullify references to your objects, to help the garbage collector with the cleanup process, but the object itself is not deleted until it is collected by the garbage collector.
If I don't delete the object, is that the object will be lying until the program ends?
No. The garbage collector will take care of deleting it, once there are no references to it anymore. The point in time when this happens is up to the garbage collector - this might also be at the end of your application.
Is there a way to check the number of active objects when a program is running?
Yes, you can use a profiler such as YourKit.
See also
When does Java's garbage collection free a memory allocation?
Garbage Collection in the Java HotSpot Virtual Machine
Java Garbage Collection Basics
What are the best practices to create a Object. ie; When I create a Object should I also make sure I delete the object once its used. If, How do I delete it?
The best practices to create a Object is just when you want to use it.
Also you need to learn about variable scoping.
If I don't delete the object, is that the object will be lying until the program ends?
No, GC will kill un referenced objects
Is there a way to check the number of active objects when a program is running?
You can use any Java profiling tool such as vesualVM
Java is a Garbage Collected language, and therefore, most memory management and cleanup is done for you. This contrary to languages like C++ where one must manually free unused memory and generally be more cautious of possible memory leaks.
To address your specific questions:
Sometimes, it is considered good practice to "null out" unused object references. This is usually only true in specific instances, for example see: Does setting Java objects to null do anything anymore?.
No, not necessarily. If there is nothing pointing to the Object in memory, then the Garbage Collector should free up the unused memory.
You could use a debugger to keep track of the number of objects that are created as you step through your code line by line (I am not sure if this is robust enough a solution for your purposes).
Java has garbage collector. Garbage collector destroys objects when it's no longer used.
you can find gc basics here](http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html)
If you want to profile application use jvisualvm , which is packaged with JDK. If you want to count objects programmatically , use JMX API's (read oracle documentation about JMX)
The JVM automatically recycles objects that are no longer in use (this is called "garbage collection"). This happens when it feels like it, and when running out of previously unallocated memory, and returns the memory used by the unused objects to the unallocated memory pool.
All you have to do is to ensure that there is no variable through which you can use the objects any more - typically by assigning another value - and the rest happens automatically.
The simplest way to see how many objects are used by your program, is to use a profiler. You can use visualvm in the JDK or the one in Netbeans for free.
I am newbie in Java and my English not enough good, I hope everyone will forgive me.
Question 1:
I have an ArrayList(J2SE) or Vector(J2ME), I have a class(example: Bullet), when i fire, i add a instance of that class to the List and after the bullets hit the target, i need to destroy them and remove them from the list. I want to ask: How to delete completely object which i need to remove, I mean: free all memory which that object was take(Same as delete pointer in C++). With normal object, we can use "= null", but in here, this object is inside a List and we can not use like that. I try to use System.gc(), but that is a bad idea, program will slow down and memory increase more than i not use gc(). If i only use List.remove(bullet_index), memory will increase a bit, but it will not decrease.
Question 2:
Have any Other idea to make a gun shot with "Unlimited number of bullet" and safe with memory.
I making a simple 2D shoting game
You simply can't. Java works over the JVM which provides a managed environment for the allocation and deallocation of your memory through a garbage collector.
You can hint the JVM to clean memory by deallocating unused objects but that's not usually the way it is meant to be used. Just remove the Bullet instance from the list, if there are no other references to it then eventually its memory will be released.
If you really want to save memory you should think about reusing the same instances, this can be done if you plan to have at most a precise amount of bullets at the same time on the screen, so instead that removing from the list the expired one you could add them to a another list which then is used to pick up new bullets (by setting their attributes). In this way you can avoid going over a certain threshold.
Java is memory managed, so you can't reliably free memory. You can be sure that memory will not be freed as long as you have pointers to your object. Setting an object to null means that nothing points to it, but doesn't necessarily mean that it will be garbage collected at that point. For an in-depth explanation on memory management in Java, check this out.
Also, avoid using vectors- they're synchronized, and usually not used in newer code.
I am currently debugging a web application which has been causing intermittent problems especially when the hit rate is high. As each new user is given a session containing personalised navigation menu I thought I would try to see how much memory the session variables need.
In a code section of the JSP which handles the creation of session objects, I added the following code:
System.gc();
long orgHeap = Runtime.getRuntime().freeMemory();
... create session variables ...
System.gc();
log.info("Heap delta: " + (Runtime.getRuntime().freeMemory() - orgHeap));
What surprised me is that adding System.gc() breaks the app. It does not work any more as some objects are getting lost (or so it seems). Values which had been initialised are null. When the gc() calls are removed the app works fine. gc() should only remove objects which have been marked for deletion - right?
Has any one else had similar problems?
The only case I can think of where this might actually happen as you describe, is if you're using WeakReferences (or expired SoftReferences, which are broadly similar in this situation) to refer to objects that you still want to keep. The objects the might get into a state where they're collectable by the GC; but until it actually runs, you'll still be able to reach them through your references. Calling System.gc(), even though it doesn't have any guaranteed semantics, might cause the collector to run and harvest all these weakly-reachable objects.
That seems unlikely, though, because
Accidentally using WeakReferences for strongly-reachable objects doesn't seem like an easy mistake to fall into. Even if you're using libraries, I find it hard to think of a case where you might feasibly end up using weak references by mistake.
If this did happen, the behaviour of the application would be undefined anyway. Garbage collections could happen at any time, so you'd likely see inconsistent behaviour without the System.gc() call. You'd always have some bit of code that runs just after a collection anyway and so couldn't find its referent object.
System.gc() doesn't theoretically do anything so it shouldn't be causing this.
That last point is the important one - why are you calling System.gc() anyway, when it is almost always counterproductive to call? I don't believe that you have a legitimate need to call it, it doesn't do anything you can rely on, and apparently it's breaking your application.
So if your app works fine without making the call, then just stop making it.
I would still consider inspecting how your app fits together though, because this is not going to be the actual cause of the problem and you likely have a deeper issue which is very fragile and just waiting to break on you later.
EDIT: Another possible reason for this could be simple timing. Calling System.gc() is likely to take a non-negligible amount of time. During this period, other threads could progress and change state in a way that the GCing thread isn't expecting. Hence when it returns from the call, the state of the world breaks its expectations and hence logic errors result. Again, this is just a guess, but is more plausible than the WeakReference one.
Garbage collection will never remove live objects, so I think your problem is elsewhere.
As you state this is under load - "hit rate is high" - this could be a case of using EJB's incorrectly, where you expect something to happen because it does so under low load (like getting the same EJB repeatedly when asking for it) but that change under high load (somebody else got that EJB, you get another).