Efficient Memory Management
in Java - Article 1
In our day to day life , we deal with classes , objects and
functions in the world of java . These are pretty much the things
which full fills all are daily needs with the help of different
design patterns and programming standards. In most of the work we
do performance has been the criteria for most of our application ,
but normally time takes the precedence over space. Due to which we
sometimes end up issues related to memory.
As we know Java is language which takes a huge heap over other
languages like C and C++ with respect to memory management. We are
no longer required to allocate and de-allocate memories in java .
During the java's life cycle , memory management has evolved a lot
with more intelligence being inducted in JVM and GC (Garbage
Collector). In the recent version of JDK (JDK 7) , a completely new
Garbage collector Algo (G1) has been introduced.
Now
the big question : THEN WHY DO WE STILL GET
MEMORY EXCEPTION
There are 2 main reasons
- Bad coding practices : Every java developer does this , in some way or the other.
- GC is unpredictable : Java provide certain guarantee regarding its GC but it's purely
impossible
to predict the GC operation at a given time.
We won't dig deep here with respect to Point (1) . This could be
eradicated by using proper coding standards , effective code review
and even by using external tools for Memory management
Coming
to Point (2) , As mentioned earlier its impossible to predict the GC
operation at a given time . The reason being very clear that , GC
internally depends on OS scheduling mechanism and OS memory
management which is not controlled by Java . Said this java provides
us with certain mechanism which can make our life easy regarding
Memory management. And the most important of them is References
Short
Description on GC in Java
Not
digging deep , GC mechanism contains basically 3 steps
- Checking if object is not reachable , if Yes
a) Check if object implements finalize() method , if so add to
finalization queue
b) Else , make the object finalized
2) If (a) section of Point (1) was true , then pick the
object from finalization queue and run the finalize method and
make object finalized
3)
Garbage collector picks the object and de–allocates the memory
**(GC
is a detailed topic and would be picked up in coming up journals)
Jumping
to References in Java
References
as going by Wikipedia 'is
a relation between objects in which one object designates'
and
nothing changes in java.
Before
Jumping into the references , we need to know about reference Queue
ReferenceQueue
as java doc says 'to
which registered reference objects are appended by the garbage
collector '
. So at a point when GC realizes that any of the reference to which
it is listening is ready for garbage collection. GC inserts that
particular object into Reference Queue .
There
are basically 4 time of Reference in java . In this article , we
would be focusing mainly on
2 type of reference
a) Strong reference :
These are most common and widely used references .
public List obj1=new ArrayList();
Here
obj1 is a strong reference
and GC can't in any case de-allocate the memory grabbed by
ArrayList until obj1
doesn't gets unreferenced ( goes out of scope) or at least it
starts pointing to another object .
But these references might not be the best choice . Specially , when
you have heavy data lying in your memory like a File Object ,a heavy
database result set etc.
This is the place where other options come into picture
b) Weak References :
As
java doc says : 'Weak
reference objects, which do not prevent their referents from being
made finalizable, finalized, and then reclaimed '.
As
the name suggest ,it sets up a weak reference to an object . For e.g.
The first parameter (k) is the object on which weak
reference is being created and the second one is the Reference
Queue (rq)
As we know, its
difficult to understand this concept without digging into the code ,
so lets pic one simple example .
We would be needing 2
simple POJO's as helper classes for our example.
Keybean.java
KeyBeanParent.java
Now lets come to a simple weak Reference
article
SimpleWeakReference.java
Output
Now
lets go point by point
Initially
we create 2 strong references for KeyBean and
KeyBeanParent parent.
(1)
–
As you could see KeyBeanParent
reference class has a Weak Refernce object for
KeyBean
, so we would assign the same object of KeyBean
created just above to the instance of KeyBeanParent
. A point to note here is we are not assigning any
reference , because usage of reference queue is optional and
WeakReference
class
provides us with 2 different constructors .
(2)
–
We
create a new instance of Reference Queue
(3)
–
This
is the place where we create a weak reference and attach the
previously created queue
(4)
- Now we hit first print statement , as you can compare with the
output section , wf.get()
returns the original object on which this weak reference was created
(5)
- This is where the weak reference concept actually begins, at this
point we simply set the reference to null and making the
referenced object only reachable through 2 weak
reference , one from wf
in the main method and one under p
( KeyBeanParent)
object's kb
reference
(6) & (7) - At this place , we try print the
values from the respective weak references and as you could see
from the output section that , both then returns the same object.
This is due to the fact that GC probably hasn't run after setting
the value to null.
(8)
- In next step we notify GC to run explicitly ( as we understand ,
its just a notification and doesn't ensure that GC would run ,
but in this case as the load is least , so we notice that GC
actually run ( This
is pure co-incidence and can't be
relied upon)
.
(9) & (10) - Here we try to print the value from
weak references and we notice that (from output ) section that
these values are null.
(11) & (12) - As GC puts the weak reference
into Refrence Queue , we can get it out using
methods like poll and remove them and print it.
Summarizing
Story of WeakRefrence
Whenever
GC finds that any particular object on heap doesn't have a strong
reference or soft reference** but is reachable through
weak reference , then it picks up this weak reference ,
disconnects it with the object and insert this weak reference into
the Reference Queue (if any) . The Object now id ready for the
process of Garbage collection.
**
Soft Reference would be a part of next article , for now you could
assume it to be another form of reference.
Why
do we need Weak Refernce
This
answered by Java in its own SDK . WeakHashMap , is one
of the classes which leverages this concept . As per documentation
of Java for this class , it says , WeakhashMap is pretty similar
to HashMap , only difference being that keys are weak references.
Now
the question is why do we need it – Lets take an example , If
suppose you are loading a gif format file and we know the
size of these files can shoot up-to 5 MB . So we decide to keep
this object in a map with a key and value pair . Now once the use of
this map object is over , we are responsible to remove it. Now
this is a additional functionality we need to implement and
manage. But this could be avoided using weakhashmap , once the GC
realizes that there is no strong reference to the key , then it
would , internally release the weak key from the map and that gif
object is released from memory.
In
the next article , we would discuss about Phantom and Soft
references.
No comments:
Post a Comment