I was reading about garbage collection and finalization in Java and when I tried an example. I click button 1, and memory jumps up. But when I click button 2, the memory didn't free up used space!
What did I do wrong and how do I free memory from unused objects?
As far as I know (I may be wrong):
When the same variable is re-instantiated again and again, the old object shall be destroyed.
When I set a variable to null the the old object shall be destroyed.
Array cells are null values. They shall be destroyed when parent array object has no variable to reference it.
How do I free up collections? How do array rules apply?
Code:
public class Memory extends javax.swing.JFrame {
Object[] object;
private void Button1ActionPerformed(java.awt.event.ActionEvent evt) {
object = new Object[10240000];
}
private void Button2ActionPerformed(java.awt.event.ActionEvent evt) {
object = null;
System.gc();
System.runFinalization();
//OR
System.runFinalization();
System.gc();
}
}
The System.gc() is only a suggestion for the JVM to clean up the memory. It may or may not take this suggestion. You are not doing anything wrong. Relax.
Java will clean unused objects out eventually, that's what garbage collector is for. You don't have to worry about it or write any code for it.
GC in Java periodically and it is not instantaneous, System.gc() only suggests that GC should run, which might not happen.
If you want to see java GC in action you should try a program with longer run-time to see what's going on with memory and GC in action.
When same variable is re-initanciated more and more the old object shall be destroyed.
When set a variable to null the the old object shall be destroyed
Array cells are null values they shall be destroyed when parent array object has no variable to reference it
How to free up collections or Array rules apply?
Answer to all four points is: Garbage collector will take care of that.
Also the reason why memory is high even though the garbage collector probably did run is that JVM takes more memory than just the objects.
Related
TLDR: How can I force the JVM not to garbage collect my objects, even if I don't want to use them in any meaningful way?
Longer story:
I have some Items which are loaded from a permanent storage and held as weak references in a cache. The weak reference usage means that, unless someone is actually using a specific Item, there are no strong references to them and unused ones are eventually garbage collected. This is all desired behaviour and works just fine. Additionally, sometimes it is necessary to propagate changes of an Item into the permanent storage. This is done asynchronously in a dedicated writer thread. And here comes the problem, because I obviously cannot allow the Item to be garbage collected before the update is finished. The solution I currently have is to include a strong reference to the Item inside the update object (the Item is never actually used during the update process, just held).
public class Item {
public final String name;
public String value;
}
public class PendingUpdate {
public final Item strongRef; // not actually necessary, just to avoid GC
public final String name;
public final String newValue;
}
But after some thinking and digging I found this paragraph in JavaSE specs (12.6.1):
Optimizing transformations of a program can be designed that reduce the number of objects that are reachable to be less than those which would naively be considered reachable. For example, a Java compiler or code generator may choose to set a variable or parameter that will no longer be used to null to cause the storage for such an object to be potentially reclaimable sooner.
Which, if I understand it correctly, means that java can just decide that the Item is garbage anyway. One solution would be to do some unnecessary operation on the Item like item.hashCode(); at the end of the storage update code. But I expect that a JVM might be smart enough to remove such unnecessary code anyway and I cannot think of any reasonable solution that a sufficiently smart JVM wouldn't be able to release sooner than needed.
public void performStorageUpdate(PendingUpdate update) {
final Transaction transaction = this.getDataManager().beginTransaction();
try {
// ... some permanent storage update code
} catch (final Throwable t) {
transaction.abort();
}
transaction.commit();
// The Item should never be garbage collected before this point
update.item.hashCode(); // Trying to avoid GC of the item, is probably not enough
}
Has anyone encounter a similar problem with weak references? Are there some language guarantees that I can use to avoid GC for such objects? (Ideally causing as small performance hit as possible.) Or am I overthinking it and the specification paragraph mean something different?
Edit: Why I cannot allow the Item to be garbage collected before the storage update finishes:
Problematic event sequence:
Item is loaded into cache and is used (held as a strong reference)
An update to the item is enqueued
Strong reference to the Item is dropped and there are no other strong references to the item (besides the one in the PendingUpdate, but as I explained, I think that that one can be optimized away by JVM).
Item is garbage collected
Item is requested again and is loaded from the permanent storage and a new strong reference to it is created
Update to the storage is performed
Result state: There are inconsistent data inside the cache and the permanent storage. Therefore, I need to held the strong reference to the Item until the storage update finishes, but I just need to hold it I don't actually need to do anything with it (so JVM is probably free to think that it is safe to get rid off).
TL;DR How can I force the JVM not to garbage collect my objects, even if I don't want to use them in any meaningful way?
Make them strongly reachable; e.g. by adding them to a strongly reachable data structure. If objects are strongly reachable then the garbage collector won't break weak references to them.
When you finish have finished the processing where the objects need to remain in the cache you can clear the data structure to break the above strong references. The next GC run then will be able to break the weak references.
Which, if I understand it correctly, means that java can just decide that the Item is garbage anyway.
That's not what it means.
What it really means that the infrastructure may be able to determine that an object is effectively unreachable, even though there is still a reference to it in a variable. For example:
public void example() {
int[] big = new int[1000000];
// long computation that doesn't use 'big'
}
If the compiler / runtime can determine that the object that big refers to cannot be used1 during the long computation, it is permitted to garbage collect it ... during the long computation.
But here's the thing. It can only do this if the object cannot be used. And if it cannot be used, there is no reason not to garbage collect it.
1 - ... without traversing a reference object.
For what it is worth, the definition of strongly reachable isn't just that there is a reference in a local variable. The definition (in the javadocs) is:
"An object is strongly reachable if it can be reached by some thread without traversing any reference objects. A newly-created object is strongly reachable by the thread that created it."
It doesn't specify how the object can be reached by the thread. Or how the runtime could / might deduce that no thread can reach it.
But the implication is clear that if threads can only access the object via a reference object, then it is not strongly reachable.
Ergo ... make the object strongly reachable.
What I mean to say through the post title is - doing this:
public static void makeNewObjectAndDoTask() {
new SomeClass().doYourTask();
}
I have myself written such code in languages such Java and JavaScript - declaring a new object without storing it in a variable, JUST to call one of its methods. Does this cause memory leaks? ..or does the object get cleared at the end of the method-stack / gets freed by the Java Garbage Collector?
Should I just be doing this instead - for safety?:
public static void makeNewObjectAndDoTask() {
SomeClass obj = new SomeClass().doYourTask();
obj = null;
//System.gc(); // Perhaps also call the collector manually?
}
As the commentors already answered, there is no memory leak in code like
public static void makeNewObjectAndDoTask() {
new SomeClass().doYourTask();
}
at least in itself, assuming that the SomeClass() constructor and the doYourTask() methods don't create memory leaks.
Definitely, the garbage collector will clean up the SomeClass instance at some time in the future.
How does it work?
Instances that are no longer accessible from program code will be garbage collected. Accessibility means being referenced in a variable, field, array element, method argument and so on.
As soon as the new SomeClass().doYourTask(); statement has finished, there is no way to access this individual SomeClass instance any more. So, it fulfills the garbage collection criteria.
The next time the garbage collector runs, it can reclaim the memory occupied by the instance (and its fields, recursively, as long as they aren't referenced elsewhere).
The alternative code
public static void makeNewObjectAndDoTask() {
SomeClass obj = new SomeClass().doYourTask();
obj = null;
}
only delays the garbage collection opportunity, as it stores a reference in obj, thus making the instance accessible for at least a tiny additional period of time, until you assign obj = null;.
Manually calling the garbage collector as in System.gc(); rarely is a good idea. It forces the GC to run (and to spend execution time on cleaning up memory), instead of relying on the JVM's highly optimized GC scheduling strategies. Don't do it unless you have a thorough understanding of the garbage collector, which led you to the conclusion that the GC strategy fails in your case.
We don't want OutOfMemoryErrors, and we don't want excessive time wasted for garbage collection, and the standard GC system does a very good job in both aspects.
duplicate - How to destroy java objects?
My question is very simple. I am new to app development with Java and am not sure whether I need to null objects after i am finished with them. for example i am using libGDX to create a game and I have several objects (Actors) being created. when I am finished with them do I simply call
obj.remove();
or should i -
obj.remove();
obj = null;
do I save memory by nulling objects or is there no advantage to be had?
No you do not need to null or manually delete objects. The java garbage collector will do this for you for any objects that have no pointers referencing them (when an object goes out of scope for example).
Generally, in java, marking the Object references as null is done to make it explicitly eligible for GC. If an object is unreachable, then it becomes eligible for GC, so, yes, you can mark it as null and let the GC do its work.
The Object will become unreachable only when there is no reference pointing to it.
example :
class MyTest {
#Override
protected void finalize() throws Throwable {
System.out.println("object is unreachable..");
}
}
// In some other class
public static void main(String[] args) {
MyTest o1 = new MyTest();
MyTest o2 = new MyTest();
System.gc();
o1 = null;
System.gc();
System.out.println("hello");
}
O/P:
hello
object is unreachable..
Here, you might have several thousand lines of code after "hello". You might want to make the GC's job easier by marking the object's references as null.
Manually nulling Objects in Java is bad, because it is slowing down most garbage collection (GC) algorithims. The GC detects by itself wether an Object is reachable or not and then it gets removed. After nulling an object the space in memory is still used and only after the GC recycles the space it can be used again. So nulling objects does not free up your space immediately. Also starting the GC manually is a bad idea. It is started by the VM if it is needed.
I want to know what all variables are garbage collected in my program and the order of garbage collection. Is there a simple way to do that:
class GarbageUtility {
public static void main(String args[]) {
int a =10;
int b = a;
int c = a + b;
System.out.println(a);
}
}
you may have a look at com.sun.management.GarbageCollectionNotificationInfo, see http://docs.oracle.com/javase/7/docs/jre/api/management/extension/com/sun/management/GarbageCollectionNotificationInfo.html
also, this post presents a way to make a gc detector for hashmaps, http://java.dzone.com/articles/letting-garbage-collector-do-c
I want to know what all variables are garbage collected in my program and the order of garbage collection. Is there a simple way to do that:
No there isn't1.
Variables are not garbage collected2. Objects are garbage collected ... or at least, they may be garbage collected.
Most of the variables in you program have type int and int is not an object / reference type. They won't even be affected by the garbage collector.
Your program won't even compile ...
Footnotes:
There are a couple of ways that you can use to infer that an object is being garbage collected:
If you declare a finalize() method, that will be called when the GC detects that the object has no strong, soft or weak references to is ... and garbage collection is imminent. You can get a similar effect with Reference objects and their associated queues. Note however that this may also change the lifetime of the respective objects ... causing them to live longer than they otherwise might.
You might be able to detect that an object is dues to be garbage collected via the external debugger or profiler agents. (I'm not sure about this. I actually think that unreachable objects are invisible to the agents.)
Actually, it is a little more complicated than that.
Variables don't have an independent lifetime. They are always part of "something else" ... and the "something else" can be garbage collected ... in some cases:
We can divide variables into 3 kinds:
Stack variables (that is method parameters and locals) are not stored in space that is managed by the GC. Any object whose reference is in a (live) stack variable won't be garbage collected.
Instance variables (instance fields declared by a class) are part of the respective object. When the object is garbage collected, the variables "go away".
Static variables (static fields declared by a class) normally stay around for the lifetime of the application. However, there are circumstances where a class may be garbage collected, and if that happens its static variables go away at the same time.
Note that GarbageCollectionNotificationInfo tells you that the GC has collected a certain heap, and gives some basic statistics such as how long the GC took and what space was available in the heap before and after.
I don't see how that helps you tell whether specific objects have been garbage collected and when it happened.
I encountered this question in an interview with following options:
How to destroy an object in java?
a. System.gc();
b. Runtime.getRuntime.gc();
c. object.delete();
d. object.finalize();
e. Java performs gc by itself, no need to do it manually.
The answer should be e?
what if e was not there? then ?
clearly c is not the answer. a and b will do gc for the whole application(question requires for one object).
I think it is d because finalize() is called just prior to gc(but is it necessary that after finalize gc is invoked ?) or I am wrong ? e must be there to answer this question ?
Answer E is correct answer. If E is not there, you will soon run out of memory (or) No correct answer.
Object should be unreachable to be eligible for GC. JVM will do multiple scans and moving objects from one generation to another generation to determine the eligibility of GC and frees the memory when the objects are not reachable.
To clarify why the other answers can not work:
System.gc() (along with Runtime.getRuntime().gc(), which does the exact same thing) hints that you want stuff destroyed. Vaguely. The JVM is free to ignore requests to run a GC cycle, if it doesn't see the need for one. Plus, unless you've nulled out all reachable references to the object, GC won't touch it anyway. So A and B are both disqualified.
Runtime.getRuntime.gc() is bad grammar. getRuntime is a function, not a variable; you need parentheses after it to call it. So B is double-disqualified.
Object has no delete method. So C is disqualified.
While Object does have a finalize method, it doesn't destroy anything. Only the garbage collector can actually delete an object. (And in many cases, they technically don't even bother to do that; they just don't copy it when they do the others, so it gets left behind.) All finalize does is give an object a chance to clean up before the JVM discards it. What's more, you should never ever be calling finalize directly. (As finalize is protected, the JVM won't let you call it on an arbitrary object anyway.) So D is disqualified.
Besides all that, object.doAnythingAtAllEvenCommitSuicide() requires that running code have a reference to object. That alone makes it "alive" and thus ineligible for garbage collection. So C and D are double-disqualified.
Short Answer - E
Answer isE given that the rest are plainly wrong, but ..
Long Answer - It isn't that simple; it depends ...
Simple fact is, the garbage collector may never decide to garbage collection every single object that is a viable candidate for collection, not unless memory pressure is extremely high. And then there is the fact that Java is just as susceptible to memory leaks as any other language, they are just harder to cause, and thus harder to find when you do cause them!
The following article has many good details on how memory management works and doesn't work and what gets take up by what. How generational Garbage Collectors work and Thanks for the Memory ( Understanding How the JVM uses Native Memory on Windows and Linux )
If you read the links, I think you will get the idea that memory management in Java isn't as simple as a multiple choice question.
Set to null. Then there are no references anymore and the object will become eligible for Garbage Collection. GC will automatically remove the object from the heap.
Here is the code:
public static void main(String argso[]) {
int big_array[] = new int[100000];
// Do some computations with big_array and get a result.
int result = compute(big_array);
// We no longer need big_array. It will get garbage collected when there
// are no more references to it. Since big_array is a local variable,
// it refers to the array until this method returns. But this method
// doesn't return. So we've got to explicitly get rid of the reference
// ourselves, so the garbage collector knows it can reclaim the array.
big_array = null;
// Loop forever, handling the user's input
for(;;) handle_input(result);
}
In java there is no explicit way doing garbage collection. The JVM itself runs some threads in the background checking for the objects that are not having any references which means all the ways through which we access the object are lost. On the other hand an object is also eligible for garbage collection if it runs out of scope that is the program in which we created the object is terminated or ended.
Coming to your question the method finalize is same as the destructor in C++. The finalize method is actually called just before the moment of clearing the object memory by the JVM. It is up to you to define the finalize method or not in your program. However if the garbage collection of the object is done after the program is terminated then the JVM will not invoke the finalize method which you defined in your program.
You might ask what is the use of finalize method?
For instance let us consider that you created an object which requires some
stream to external file and you explicitly defined a finalize method to this object which checks wether the stream opened to the file or not and if not it closes the stream. Suppose, after writing several lines of code you lost the reference to the object. Then it is eligible for garbage collection. When the JVM is about to free the space of your object the JVM just checks have you defined the finalize method or not and invokes the method so there is no risk of the opened stream. finalize method make the program risk free and more robust.