Here is my code:
LinkedList <Mono> list = new LinkedList ();
list.add(new Mono (2, 2));
list.add(new Mono (1, -1));
list.remove (1);
Now, when the second item in the list is removed, is the object destroyed? IE, it undergoes garbage collection?
EDIT for new question:
Yes, the object will be eligible for garbage collection when there are no strong references remaining. However the JVM will try to do clean up garbage in big batches, so it could actually get collected at any arbitrary later time (or never if the JVM terminates before GC gets around to it)
Old answer:
Class unloading is a rare event, and will generally not happen in a timely manner (if at all.)
Specifically, even after it becomes eligible for collection it won't get collected along with "normal" new objects like your Mono instances - it's often in a special different pool (PermGen in the Oracle JVM)
You should assume that once a class is loaded it will stay loaded forever. Once you get into web applications in containers this is not always true, but anyone that has worked in those environments can tell you generally how well it (doesn't) work.
Garbage Collection in Java is generally non-deterministic insofar as when it will occur and which eligible objects the GC will evict ("free") when a GC cycle does occur.
The only reliable rule is thus:
An object will remain available (will not be GC'ed/freed/evicted) as long as it is strongly-reachable. (See "The Reachability Lifecycle of Objects" in Chapter 9 of Inside the Java Virtual Machine for what this means -- very good reading in general, if a tad dated.)
In the posted code the remove will result in the second object new Mono(1, -1) being eligible for reclamation as there are no longer any strong references to it (the object is no longer strongly-reachable). The actual eviction (if it occurs) will happen "sometime later" and may not even be the next GC cycle. Using finalizers (ick) further complicates the matter.
Note that an object is never guaranteed to be GC'ed (the JVM may just terminate [ab]normally, for instance) and the exact semantics of particular GC implementation can differ and still be a conforming virtual machine -- it all comes down to reachability.
Happy coding.
Do you mean when the Object is unloaded?
An empty list is still a list, so it'll stay in memory. It is cleared when you go:
list=somethingElse;
That is assuming that you don't assign anything else to be list.
As far as the class definition itself, it should stay in memory forever. Class definitions are in the permanent generation.
As a side note. list cannot be garbage collected at that point. Because you can add things to it after if you clear it.
the second object will be elligible for gargabe collection after removing it from the list, since there will be no more references to it .. hence out of scope .
hope this helped
Lots of answers, so here's my spin. Think about "scope", a concept in computer languages that describes where and when you can access a named bit of memory.
Here's your original code, with your purported removal of the second list member added:
LinkedList <Mono> list = new LinkedList ();
list.add(new Mono (2, 2));
list.add(new Mono (1, -1));
list.remove (1);
list.remove (2);`
At the point of list.remove(2), the object "list" can still be referenced. Sure, it's empty, but then you might decide to add a new Mono to it. You can because "list" is still in scope, so "list" is not reclaimed.
Compare to this:
{
LinkedList <Mono> list = new LinkedList ();
list.add(new Mono (2, 2));
list.add(new Mono (1, -1));
list.remove (1);
list.remove (2);`
}
After the closing brace, "list" can no longer be referenced. "list" was declared inside that scope, and when the scope was exited, "list" was removed from the namespace along with the scope itself. At that point, garbage collection could happen, since no one could possibly use "list" again.
Keep an eye on the scope of your objects. If you want to influence garbage collection, keep the scope of your objects limited to the region where they are used. As it happens, that is good programming style too.
I guess people got confused with the terminology you used. I believed you are asking if your Mono object will be "deleted"/"garbage collected".
Let's take a look at the remove(1) that you are invoking...
This is the remove function that you are calling as defined in java.util.LinkedList:
public E remove(int index) {
return remove(entry(index));
}
The function above calls the following (look at my comments in the code):
private E remove(Entry<E> e) {
if (e == header)
throw new NoSuchElementException();
E result = e.element;
e.previous.next = e.next; //Preceding element refers now to the one after the element to be removed;
e.next.previous = e.previous; //Next element refers now to the one before the one to be removed;
e.next = e.previous = null; //Element to be removed doesn't refer to anything anymore;
e.element = null;
size--;
modCount++;
return result;
}
After the function you call terminates, there is no way to refer to your Mono(1, -1) anymore. That Mono Object is not accessible anymore. This means that it will become eligible for Garbage Collection. Keep in mind that "eligible" might mean that it never be garbage collected... More on GC here.
The simple answer is that it should not matter to you when a Java object is garbage collected. The only thing that you need to know is that it will get garbage collected before your program runs out of memory ... provided that the object is unreachable.
The complicate answer includes other things:
The garbage collector typically runs at a time that you can't predict.
You can call System.gc() to suggest that the JVM runs the GC run now, but:
the JVM may ignore this hint, and
it is generally a bad idea to do this. (Running the GC is expensive, and your application has insufficient information to know when it is best to do this from an efficiency standpoint.)
Any particular run of the GC is not guaranteed to reclaim all unreachable objects. The GC has a lot of "smarts" that are aimed at making GC as efficient as possible, or reducing "pause" times. One of the "smarts" is to not GC the entire heap every time.
There are no guarantees that the GC will run at all, or that it will run before the JVM is shutdown.
Because of the above, it is a bad idea to write an application so that it depends on a specific object being reclaimed / deleted at a specific time.
(The one thing that should concern you in memory management is storage leaks; e.g. when your application keeps references to unwanted objects that prevent those objects from ever becoming unreachable. But that's not what your question is about.)
The class "Mono" cannot be unloaded since there are still references to it. The type of the list refers to it and there is still one element in the list.
I suppose you did not mean to ask whether the class is unloaded, but whether the instance is "unloaded". Each instance of a class, each object, is allocated on the heap. When the object is no longer in use, the space that it occupies in the heap can be reclaimed. This does not happen immediately however. All JVM implementations that I know use a garbage collector to clean up the memory. To really simplify things here: when there is no more space free to create a new object on the heap, the garbage collector kicks in and will check which parts of the heap are still in use. The parts that are no longer in use, can be reused for new objects.
So, the memory from an object that is no longer in use, will only be reclaimed when the garbage collector kicks in. And this is something that cannot be predicted.
Do you mean is the instance of Mono eligible for garbage collection or is the instance of list eligible for garbage collection?
The instance of mono will be eligible for garbage collection when it is removed (assuming that the code has not created over references to it.
The list is NOT eligible for garbage collection just because it is emptied. An empty list cannot be garbage collected because it is a valid object that can read and written to again.
An as others have pointed out. We are talking about eligible for garbage collection. The garbage collector does not necessarily run immediately.
Related
Just trying to understand something from GC viewpoint
public Set<Something> returnFromDb(String id) {
LookupService service = fromSomewhere();
Map<String,Object> where = new WeakHashMap<>() {}
where.put("id",id);
return service.doLookupByKVPair(where); // where doesn't need to be serializable
}
what I understand is that once this method call leaves the stack, there is no reference to where regardless of using HashMap or WeakHashMap - but since weak reference is weakly reachable wouldn't this be GCd faster? But if the method call leaves the stack, then there is no reachable reference anyway.
I guess the real question that I have is - "Would using WeakHashMap<> here actually matters at all" - I think it's a "No, because the impact is insignificant" - but a second answer wouldn't hurt my knowledge.
When you use a statement like where.put("id",id); you’re associating a value with a String instance created from a literal, permanently referenced by the code containing it. So the weak semantic of the association is pointless, as long as the code is reachable, this specific key object will never get garbage collected.
When the entire WeakHashMap becomes unreachable, the weak nature of the references has no impact on the garbage collection, as unreachable objects have in general. As discussed in this answer, the garbage collection performance mainly depends on the reachable objects, not the unreachable ones.
Keep in mind the documentation:
The relationship between a registered reference object and its queue is one-sided. That is, a queue does not keep track of the references that are registered with it. If a registered reference becomes unreachable itself, then it will never be enqueued. It is the responsibility of the program using reference objects to ensure that the objects remain reachable for as long as the program is interested in their referents.
In other words, a WeakReference has no impact when it is unreachable, as it will be treated like any other garbage, i.e. not treated at all.
When you have a strong reference to a WeakHashMap while a garbage collection is in progress, it will reduce the performance, as the garbage collector has to keep track of the encountered reachable WeakReference instances, to clear and enqueue them if their referent has not been encountered and marked as strongly reachable. This additional effort is the price you have to pay for allowing the earlier collection of the keys and the subsequent cleanup, which is needed to remove the strongly referenced value.
As said, when, like in your example, the key will never become garbage collected, this additional effort is wasted. But if no garbage collection happens while the WeakHashMap is used, there will be no impact, as said, as the collection of an entire object graph happens at once, regardless of what kind of objects are in the garbage.
This question already has answers here:
Declaring variables inside or outside of a loop
(20 answers)
Closed 8 years ago.
I know similar question has been asked many times previously but I am still not convinced about when objects become eligible for GC and which approach is more efficient.
Approach one:
for (Item item : items) {
MyObject myObject = new MyObject();
//use myObject.
}
Approach Two:
MyObject myObject = null;
for (Item item : items) {
myObject = new MyObject();
//use myObject.
}
I understand: "By minimizing the scope of local variables, you increase the readability and maintainability of your code and reduce the likelihood of error". (Joshua Bloch).
But How about performance/memory consumption? In Java Objects are Garbage collected when there is no reference left to the object. If there are e.g. 100000 items then 100000 objects will be created. In Approach One each object will have a reference (myObject) to it so they are not eligible for GC?
Where as in Approach Two with every loop iteration you are removing reference from the object created in previous iteration. so surely objects start becoming eligible after the first loop iteration.
Or is it a trade off between performance and code readability & maintainability?
What have I misunderstood?
Note:
Assuming I care about performance and myObject is not needed after the loop.
Thanks In Advance
If there are e.g. 100000 items then 100000 objects will be created in Approach One and each object will have a reference (myObject) to it so they are not eligible for GC?
No, from Garbage Collector's point of view both the approaches work the same i.e. no memory is leaked. With approach two, as soon as the following statement runs
myObject = new MyObject();
the previous MyObject that was being referenced becomes an orphan (unless while using that Object you passed it around, say, to another method where that reference was saved) and is eligible for garbage collection.
The difference is that once the loop runs out you would have the last instance of MyObject still reachable through the myObject reference originally created outside the loop.
Does GC know when references go out of scope during the loop execution or it can only know at the end of method?
First of all there's only one reference, not references. It's the objects that are getting unreferenced in the loop. Secondly, the garbage collection doesn't kick in spontaneously. So forget the loop, it may not even happen when the method exits.
Notice that I said, orphan objects become eligible for gc, not that they get collected immediately. Garbage collection never happens in real time, it happens in phases. In the mark phase, all the objects that are not reachable through a live thread anymore are marked for deletion. Then in the sweep phase, memory is reclaimed and additionally compacted much like defragmenting a hard drive. So, it works more like a batch rather than piecemeal operations.
GC isn't bothered about scopes or methods as such. It only looks for unreferenced objects and it does so when it feels like doing it. You can't force it. The only thing that you can be sure of is that GC would run if the JVM is running out of memory but you can't pin exactly when it would do so.
But, all this does not mean that GC can't kick in while the method executes or even while the loop is running. If you had, say, a Message Processor that processed 10,000 messages every 10 mins or so and then slept in between i.e. the bean waits within the loop, does 10,000 iterations and then waits again; GC would definitely kick into action to reclaim memory even though the method hasn't run to completion yet.
You have misunderstood when objects become eligible for GC - they do this when they are no longer reachable from an active thread. In this context that means:
When the only reference to them goes out of scope (approach 1).
When the only reference to them is assigned another value (approach 2).
So, the instance of MyObject would be eligible for GC at the end of each loop iteration whichever approach was used. The difference (theoretically) between the two approaches is that the JVM would have to allocate memory for a new object reference each iteration in approach 1 but not in approach 2. However, this assumes the Java compiler and/or Just-In-Time compiler is not smart to optimise approach 1 to actually act like approach 2.
In any case, I would go for the more readable and less error prone approach 1 on the grounds that:
The performance overhead for a single object reference allocation is tiny.
It will probably get optimised away anyway.
In both approaches objects will get Garbage collected.
In Approach 1: As and when for loop exits , all the local variable inside for loop get Garbage collected , as the loop ends.
In Approach 2 : As when new new reference is assigned to myObject variable the earlier has no proper reference .So that earlier get garbage collected and so on until loop runs.
So in both approaches there is no performance bottle neck.
I would not expect declaring the variable inside a block to have a detrimental impact on performance.
At least notionally the JVM allocates the stack frame at the start of the method and destroys it at the end. By implication will have the cumulative size to accommodate all the local variables.
See section 2.6 in here:
http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html
That is consistent with other languages such as C where resizing the stack frame as the function/method executes is an overhead with no apparent return.
So wherever you declare it shouldn't make a difference.
Indeed declaring variables in blocks may help the compiler realize that the effective size of the stack frame can be smaller:
void foo() {
int x=6;
int y=7;
int z=8;
//.....
}
Versus
void bar() {
{
int x=6;
//....
}
{
int y=7;
//....
}
{
int z=8;
//....
}
}
Notice that bar() clearly only needs one local variable not 3.
Though making the stack frame smaller is unlikely to have any real influence on performance!
However when a reference goes out of the scope may make the object it references available for garbage collection. You would otherwise need to set references to null which is an untidy and unnecessary bother (and tinsy weenie overhead).
Without question you should declare variables inside a loop if (and only if) you don't need to access them outside the loop.
IMHO blocked statements (like bar has above) are under used.
If a method proceeds in stages you can protect the later stages from variable pollution using blocks.
With suitable (short) comments it can often be more readable (and efficient) way of structuring code than breaking it down it lost of private methods.
I have a chunky algorithm (Hashlife) where making earlier artifacts available for garbage collection during the method can make the difference between getting to the end and getting OutOfMemoryError.
In this query remove() method has following implementation.
/**
* remove() removes "node" from this DList. If "node" is null, do nothing.
* Performance: runs in O(1) time.
*/
public void remove(DListNode node) {
if((node != null) && (node.listp == this)){
node.prev.next = node.next;
node.next.prev = node.prev;
}
this.size--;
}
After the execution of this remove() method, There would not be any inward pointer pointing to object unless the user of DList class still points to this node using some reference variable.
My question:
When and How does garbage collector trash this object after none of the reference pointers point to this object? Because How can GC get control of that object without any reference to it?
An object may be GC'ed/reclaimed at any point after it is no longer strongly reachable. An object is strongly reachable if and only if it can be reached (via strong references) from a GC root. That is, the GC reclaiming an object - if and when it chooses to do so - is merely a consequence of not being able to access said object.
Now, the one thing that Java guarantees is that it will try it's best (which may involve doing nothing) to free memory before throwing an OOM.
Even though there are no strong references from the code doesn't mean that the JVM isn't tracking the object or that it has vanished! The object still exists - even though it is not strongly reachable (read: not accessible) from user code - until/when such is actually GC'ed.
This allows for some interesting cases, eg.
A finalizer has a this - access to the object to be GC'ed! - and can "relife" (or "resurrect") objects, which is bad. Note: while a finalizer being called roughly implies the object is finally going to be GC'ed; a finalizer is not guaranteed to be called, ever, etc.
ReferenceQueues and the *Reference types can be used to track objects that are no longer strongly reachable and thus are elligble to be GC'ed even though a strong reference may still be obtainable - and obtaining such would remove the reclaimable status.
It is undefined. It could happen the next time the garbage collector runs (it can ONLY happy when the garbage collector runs), but that is not guarenteed - Not all garbage is necessarily cleaned with each gc run
Java's GC does not trash an object as soon as it's not used anymore. Instead, GC runs from time to time, checking objects' usage and emptying memory.
You cannot tell GC to run arbitrarily, but you can request it to run by calling System.gc(). However, calling gc() does not run GC AT THIS TIME... it will only request the System to run it.
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.
Hopefully a simple question. Take for instance a Circularly-linked list:
class ListContainer
{
private listContainer next;
<..>
public void setNext(listContainer next)
{
this.next = next;
}
}
class List
{
private listContainer entry;
<..>
}
Now since it's a circularly-linked list, when a single elemnt is added, it has a reference to itself in it's next variable. When deleting the only element in the list, entry is set to null. Is there a need to set ListContainer.next to null as well for Garbage Collector to free it's memory or does it handle such self-references automagically?
Garbage collectors which rely solely on reference counting are generally vulnerable to failing to collection self-referential structures such as this. These GCs rely on a count of the number of references to the object in order to calculate whether a given object is reachable.
Non-reference counting approaches apply a more comprehensive reachability test to determine whether an object is eligible to be collected. These systems define an object (or set of objects) which are always assumed to be reachable. Any object for which references are available from this object graph is considered ineligible for collection. Any object not directly accessible from this object is not. Thus, cycles do not end up affecting reachability, and can be collected.
See also, the Wikipedia page on tracing garbage collectors.
Circular references is a (solvable) problem if you rely on counting the references in order to decide whether an object is dead. No java implementation uses reference counting, AFAIK. Newer Sun JREs uses a mix of several types of GC, all mark-and-sweep or copying I think.
You can read more about garbage collection in general at Wikipedia, and some articles about java GC here and here, for example.
The actual answer to this is implementation dependent. The Sun JVM keeps track of some set of root objects (threads and the like), and when it needs to do a garbage collection, traces out which objects are reachable from those and saves them, discarding the rest. It's actually more complicated than that to allow for some optimizations, but that is the basic principle. This version does not care about circular references: as long as no live object holds a reference to a dead one, it can be GCed.
Other JVMs can use a method known as reference counting. When a reference is created to the object, some counter is incremented, and when the reference goes out of scope, the counter is decremented. If the counter reaches zero, the object is finalized and garbage collected. This version, however, does allow for the possibility of circular references that would never be garbage collected. As a safeguard, many such JVMs include a backup method to determine which objects actually are dead which it runs periodically to resolve self-references and defrag the heap.
As a non-answer aside (the existing answers more than suffice), you might want to check out a whitepaper on the JVM garbage collection system if you are at all interested in GC. (Any, just google JVM Garbage Collection)
I was amazed at some of the techniques used, and when reading through some of the concepts like "Eden" I really realized for the first time that Java and the JVM actually could beat C/C++ in speed. (Whenever C/C++ frees an object/block of memory, code is involved... When Java frees an object, it actually doesn't do anything at all; since in good OO code, most objects are created and freed almost immediately, this is amazingly efficient.)
Modern GC's tend to be very efficient, managing older objects much differently than new objects, being able to control GCs to be short and half-assed or long and thorough, and a lot of GC options can be managed by command line switches so it's actually useful to know what all the terms actually refer to.
Note: I just realized this was misleading. C++'s STACK allocation is very fast--my point was about allocating objects that are able to exist after the current routine has finished (which I believe SHOULD be all objects--it's something you shouldn't have to think about if you are going to think in OO, but in C++ speed may make this impractical).
If you are only allocating C++ classes on the stack, it's allocation will be at least as fast as Java's.
Java collects any objects that are not reachable. If nothing else has a reference to the entry, then it will be collected, even though it has a reference to itself.
yes Java Garbage collector handle self-reference!
How?
There are special objects called called garbage-collection roots (GC roots). These are always reachable and so is any object that has them at its own root.
A simple Java application has the following GC roots:
Local variables in the main method
The main thread
Static variables of the main class
To determine which objects are no longer in use, the JVM intermittently runs what is very aptly called a mark-and-sweep algorithm. It works as follows
The algorithm traverses all object references, starting with the GC
roots, and marks every object found as alive.
All of the heap memory that is not occupied by marked objects is
reclaimed. It is simply marked as free, essentially swept free of
unused objects.
So if any object is not reachable from the GC roots(even if it is self-referenced or cyclic-referenced) it will be subjected to garbage collection.
Simply, Yes. :)
Check out http://www.ibm.com/developerworks/java/library/j-jtp10283/
All JDKs (from Sun) have a concept of "reach-ability". If the GC cannot "reach" an object, it goes away.
This isn't any "new" info (your first to respondents are great) but the link is useful, and brevity is something sweet. :)