Why aren't Java weak references counted as references during garbage collection? - java

Why are Java weak references not counted as references with respect to garbage collection?

Because that is simply its purpose.
An object is garbage collected if 0 references are pointing at it. Since a weak reference should not, on its own, prevent an object from being garbage collected, it is not counted during GC.
Have a look at the various definitions of Reachability to get a clear picture:
Package java.lang.ref Description: Reachability

Weak references are not counted as references under GC because that is the whole point of their existence and their definition: references that do not cause the object they point to to be considered live.
This is very useful because it lets you maintain relationships among objects which automatically go away when you are no longer interested in those objects.
You can extend objects with properties, without causing objects to become permanently linked into the reachability graph (turning into "semantic garbage" when no longer needed).
For example, a global weak hash table could let you find all of the Student objects belonging to a given Course and vice versa: all the Course objects belonging to a Student.
If a Student becomes garbage (you lose all your references to it), the weak hash table will automatically remove the entry associating that Student with its Course objects.
The advantage is that you didn't have to add a list of students into the Course class. And also, when you want to get rid of a Student, you do not have to hunt down every Course object and remove that student from its list.
Just lose track of the Student "naturally" and the weak hash table will purge itself.

Related

Should object be explicitly deleted after removing it from a Vector?

Let's say I have a Vector v that contains 100 objects of class Scenario which is composed of 10 different types of objects.In order to permanently delete Scenario and all its objects at index 5 of Vector v , which one of the following is correct way.
1. v.removeElementAt(5);
OR:
2. Scenario s=(Scenario) v.elementAt(5);
v.removeElementAt(5);
s=null;
OR:
3. Scenario s=(Scenario) v.elementAt(5);
s.makeAllObjectsNull();//explicitly assign null to 10 objects inside Scenario e.g. object1=null object2=null and so on
v.removeElementAt(5);
s=null;
Does an object need to be explicitly deleted after deleting it from a Vector?
in simple word, all object that haven't any reference from another object is legible to be GC.
So any case of your code get that condition, then the object will be GC.
for example if a Scenario object has only referent from that vector, then:
v.removeElementAt(5);
the only reference has gone, and it will be legible to be GC.
another thing to tell here.
when you doing this:
Scenario s = (Scenario) v.elementAt(5);
v.removeElementAt(5);
s = null;
You just declared another reference s and then set it to null, so it's not necessary to this.
You never explicitly delete an object in Java. The garbage collector may automatically free an object's memory when it is no longer reachable. Usually you don't have to think about it, other than:
Some objects hold external resources other than memory. Those must be disposed of explicitly, sometimes through the java.io.Closeable interface.
Unintentional object retention can occur if a variable outlives the useful lifespan of the object to which it refers. In these cases, it can be useful to set the object to null. But these are the exception.
"Nulling out object references should be the exception rather than the norm. The best way to eliminate an obsolete reference is to let the variable that contained the reference fall out of scope. This occurs naturally if you define each variable in the narrowest possible scope." -- from "Effective Java," 2nd ed., by Joshua Bloch.
For your specific case:
Let's say I have a Vector v that contains 100 objects of class Scenario which is composed of 10 different types of objects.
Note that your vector does not contain objects. It contains references to objects. There may be other references to the same objects.
1.
v.removeElementAt(5);
This removes the reference to the object from the vector. The object is eligible for collection if no other references to it remain.
OR
Scenario s=(Scenario) v.elementAt(5);
v.removeElementAt(5);
s=null;
This has no value. It assigns an additional reference and promptly forgets that reference. Setting a single reference to null does not cause object disposal. The object is eligible for disposal if and only if there are no other external references.
OR
Scenario s=(Scenario) v.elementAt(5);
s.makeAllObjectsNull();//explicitly assign null to 10 objects inside Scenario e.g. object1=null object2=null and so on
v.removeElementAt(5);
s=null;
This is also unnecessary.
You don't have any objects inside the Scenario object. You may have references to objects. The garbage collector is looking for unreachable objects. It can handle disconnected graphs of references.
If the Scenario itself becomes unreachable, then setting its fields to null has no effect on the reachability of the objects referenced by its fields.
It depends on your case.
If u have no more links on scenario object and vector is a storage for your scenarios, then you can just remove it from collection and garbage collector remove it and its children elements from memory. It is the case of aggregation
If scenario is stored in some other storage and vector is used to associate your scenario with some other information (but scenario is stored under some other entity), then removing from vector means remove just association between your scenario and some info. Then scenario will stay in your system with all state. It is the case of composition

Delete/free a linked list node in Java. Suggestion please

All,
If I were to write a function to delete a node (given headNode and data as input parameters) from a linkedList in Java. I would find the node that has "node.data=data", and delete it by pointing its previous node to its next node *^. My question is, do we have to point the "to be deleted" node to null? to free the memory? or the GC will take care of objects no more accessed in heap.
*^: say A->B->C->D , if B.data=data, then make A->C . is B->Null necessary?
please let me know if its not clear, I will edit it. Thanks.
If you want to delete Node B you just need for A to point to C. The garbage collector will take care of your B nodes as there won't be any references left to it.
The following explanation is quoted from http://javarevisited.blogspot.com/2011/04/garbage-collection-in-java.html
An Object becomes eligible for Garbage collection or GC if its not reachable from any live threads or any static refrences in other words you can say that an object becomes eligible for garbage collection if its all references are null. Cyclic dependencies are not counted as reference so if Object A has reference of object B and object B has reference of Object A and they don't have any other live reference then both Objects A and B will be eligible for Garbage collection.
Generally an object becomes eligible for garbage collection in Java on following cases:
1) All references of that object explicitly set to null e.g. object = null
2) Object is created inside a block and reference goes out scope once control exit that block.
3) Parent object set to null, if an object holds reference of another object and when you set container object's reference null, child or contained object automatically becomes eligible for garbage collection.
4) If an object has only live references via WeakHashMap it will be eligible for garbage collection.
As everyone has said you don't need to set it to null. I just want to add that I had a similar question before which might not be obvious. If you have a doubly linked list, where each node references the previous and the next node, for example A-B-C-D and you remove C-D so that you're left with A-B. You also do not need to worry about C or D even though both of them still have a reference to them (from the other one). Apparently the GC is smart enough to take care of that case as well
No you don't have to set B to null. The Java garbage collector will free the memory for any object not reachable anymore.

Question about Garbage Collection in Java

Suppose I have a doubly linked list. I create it as such:
MyList list = new MyList();
Then I add some nodes, use it and afterwards decide to throw away the old list like this:
list = new MyList();
Since I just created a new list, the nodes inside the old memory area are still pointing to each other. Does that mean the region with the old nodes won't get garbage collected? Do I need to make each node point to null so they're GC'd?
No, you don't. The Java GC handles cyclic references just fine.
Conceptually, each time the GC runs, it looks at all the "live" root references in the system:
Local variables in every stack frame
"this" references in every instance method stack frame
Effectively, all static variables (In fact these are really referenced by Class objects, which are in turn referenced by ClassLoaders, but lets ignore that for the moment.)
With those "known live" objects, it examines the fields within them, adding to the list. It recurses down into those referenced objects, and so on, until it's found every live object in the system. It then garbage collects everything that it hasn't deemed to be live.
Your cyclically referenced nodes refer to each other, but no live object refers to them, so they're eligible for garbage collection.
Note that this is a grossly simplified summary of how a garbage collector conceptually works. In reality they're hugely complicated, with generations, compaction, concurrency issues and the like.
If you created your own double linked list, and you put in this double linked list Containers (that contain items from your list); only those containers are linked one to another.
So in your list you'll have an object A contained in A'. A' is linked to B' and B' is a container that hold B etc. And none of the object have to reference another.
In a normal case those containers won't be available from outside (only the content is interesting); so only your list will have references to your containers (remember that your content isn't aware of his container).
If you remove your last reference to your list (the list, not the container nor the content) the GC will try to collect your list content, witch is your containers and your contents.
Since your containers are not available outside the only reference they have is one each other and the main list. All of that is called an island of isolation. Concerning the content, if they still have references in your application, they will survive the GC, if not they won't.
So when you remove your list only A' and B' will be deleted because even if they still have references, those references are part of an island. If A and B have no more references they will be deleted too.
No -- Java (at least as normally implemented) doesn't use reference counting, it uses a real garbage collector. That means (in essence) when it runs out of memory, it looks at the pointers on the stack, in registers, and other places that are always accessible, and "chases" them to find everything that's accessible from them.
Pointers within other data structures like your doubly-linked list simply don't matter unless there's some outside pointer (that is accessible) that leads to them.
No, the GC will reclaim them anyways so you don't need to point them to null. Here's a good one paragraph description from this JavaWorld article:
Any garbage collection algorithm must
do two basic things. First, it must
detect garbage objects. Second, it
must reclaim the heap space used by
the garbage objects and make it
available to the program. Garbage
detection is ordinarily accomplished
by defining a set of roots and
determining reachability from the
roots. An object is reachable if there
is some path of references from the
roots by which the executing program
can access the object. The roots are
always accessible to the program. Any
objects that are reachable from the
roots are considered live. Objects
that are not reachable are considered
garbage, because they can no longer
affect the future course of program
execution.
The garbage collector looks if objects are referenced by live threads. If objects are not reachable by any live threads, they are eligible for garbage collection.
It doesn't matter if the objects are referencing each other.
As others have pointed out, the Java garbage collector doesn't simply look at reference counting; instead it essentially looks at a graph where the nodes are the objects that currently exist and links are a reference from one object to another. It starts from a node that is known to be live (the main method, for instance) and then garbage collects anything that can't be reached.
The Wikipedia article on garbage collection discusses a variety of ways that this can be done, although I don't know exactly which method is used by any of the JVM implementations.
The garbage collector looks for objects that isn't referenced anywhere.
So if you create a object and you loose the reference like the example the garbage collector will collect this.

Is this scenario suitable for WeakReferences?

I am working on querying the address book via J2ME and returning a custom
Hashtable which I will call pimList. The keys in pimList {firstname, lastname} maps to an object (we'll call this object ContactInfo) holding (key, value) pairs e.g. work1 -> 44232454545, home1 -> 44876887787
Next I take firstName and add it into a tree.
The nodes of the tree contains the characters from the firstName.
e.g. "Tom" would create a tree with nodes:
"T"->"o"->"m"-> ContactInfo{ "work1" -> "44232454545", "home1" -> "44876887787" }
So the child of the last character m points to the same object instance in pimList.
As I understand it, the purpose of WeakReferences is to that its pointer is weak and the object it points to can be easily GC'ed. In a memory constraint device like mobile phones, I would like to ensure I don't leak or waste memory. Thus, is it appropriate for me to make:
pimList's values to be a WeakReference
The child of node "m" to point to WeakReference
?
It should work. You will need to handle the case where you are using the returned Hashtable and the items are collected however... which might mean you want to rethink the whole thing.
If the Hashtable is short lived then there likely isn't a need for the weak references.
You can remove the items out of the Hashtable when you are done with them if you want them to be possibly cleaned up while the rest of the Hashtable is stll being used.
Not sure I exactly understood what you try to do but an objects reachability is determined by the strongest reference to it (hard reference is stronger than soft reference which is stronger than weak reference which is stronger than phantom reference).
Hard referenced objects won't be garbage collected. Soft referenced objects will be garbage collected only if JVM runs out of memory, weak referenced objects will be garbage collected as soon as possible (this is theory it depends on the JVM and GC implementation).
So usually you use softreference to build a cache (you want to reference information as long as possible). You use weakreference to associate information to an object that is hard referenced somewhere, so if the hardreferenced object is no longer referenced the associated information can be garbage collected - use weakhashmap for that.
hope this helps...
I am not sure if the WeakMap is the right thing here. If you do not hold strong references anywhere in your application, the data in the map will disappear nearly immediately, because nobody is referencing it.
A weak map is a nice thing, if you want to find things again, that are still in use elsewhere and you only want to have one instance of it.
But I might not get your data setup right... to be honest.

What is object graph in java?

Whenever I study Garbage Collector I hear the term object Graph. What does it mean exactly?
Objects have references to other objects which may in turn have references to more objects including the starting object. This creates a graph of objects, useful in reachability analysis. For instance, if the starting object is reachable (say it's in a thread's local stack) then all objects in the graph are reachable and an exact garbage collector cannot harvest any of these objects. Similarly, starting with a set of live objects (roots) if we create a list of all reachable objects, all other objects are garbage - fair game for collection.
An 'Object Graph' is the conceptualization of all instances of the objects from your object model (the classes in your program) and their interconnections.
Take for example:
You have two classes
Class Foo
{
String aString = "foo";
Bar aBar;
}
Class Bar
{
String aString = "boo";
}
If you were to create an instance, Foo myFoo and then create an instance of Bar myBar, and connect them, myFoo.aBar = myBar;, your object graph would consist of a single instance of Foo with a reference to a single instance of Bar.
The garbage collector essentially uses the object graph to determine which instances in memory are still linked to something and possibly needed by the program, and which instances are no longer accessible and therefore can be deleted.
Someone on wikipedia puts it more eloquently than me:
Object-oriented applications contain
complex webs of interrelated objects.
Objects are linked to each other by
one object either owning or containing
another object or holding a reference
to another object. This web of objects
is called an object graph and it is
the more abstract structure that can
be used in discussing an application's
state.
Object graph is basically a dependency graph between objects
It is used to determine which objects are reachable and which not, so that all unreachable objects could be made eligible for garbage collection.
What we are talking about is the mathematical notion of a directed graph that consists of nodes and edges that connect the nodes. An object graph is some graph whose nodes are objects, and whose edges are relationship of interest between the objects.
In the case of the Java garbage collector, the object graph of concern is the graph of reachable objects. In this graph, the nodes are Java objects, and the edges are the explicit or implied references that allow a running program to "reach" other objects from a given one. (For example of an implied reference, there is an implied reference from an object to it's Class object, and hence to the heap objects holding the classes statics and its code ... but I digress.)
As #Chandra Patni explained, garbage collection works by traversing the reachability graph consisting of all objects that can be reached from one of a set of starting points; the "root set" in GC terminology. Any object that is not found in this graph traversal can no longer influence the computation, and is therefore eligible to be garbage collected.
Object graph is a network of instances of classes of our application/software that currently exist in memory.
Click to see image: http://blog.ploeh.dk/content/binary/Windows-Live-Writer/Compose-object-graphs-with-confidence_921A/Tree_1.png
It can be a long chain of objects to a short one object graph also. E.g.: lets say we have classes like PetDog, Owner, PetKennel in a application. Now, PetDog has owner, Owner have one or many PetDog, PetDog is trained from a PetKennel and a PetKennel trains many PedDog. Now on implementation of those relationships in Object Oriented Approach we, a Owner (lets say you: a instance/object of Owner class) might reference (link to) many PetDog instances (if you have many dogs else you reference to only one PetDog), again a PetDog references to its particular owner instance/object (that is you in your's dogs case, Mr. John will be referenced by (linked to) his dog), you might have bought pet dog from different kennel club (where dogs are trained and sold also) then each of PetDog instances/objects references/linked to their particular Kennel clubs. This creates a complex network of objects related to each other.
If you happen to represent each instances/objects (each objects of PetDog, Owner, PetKennel) as circle/square (or any shape) in your note/sketch book and draw arrow or lines to represent who object is linked (referencing) with which object then you create a object graph.
Sometime it happens that when you delete or change links between those instances of any class then some instances might not be referenced (linked) to any other instances which will be removed by garbage collector.
As we know Objects are instance of a Class.
An Object may have reference to the other object (use of Pointers for addressing).
Also these objects may have reference to another object and so on leading into a Hierarchy of Objects references to each other.
This is an Object Graph.

Categories