If you have any doubts in the below, contact us by dropping a mail to the Kung Fu Panda.
We will get back to you very soon.
Problems with Explicit Memory Management.
Suppose Object A refers to Object B. however, we deallocate the space available to B. Now when A refers to B, we cannot be sure what will happen. A holds a dangling reference to B.
memory leaks happen when memory is allocated, but the object is not referenced anymore. Since the object memory is not specifically deallocated, there is a space leak.
If in a linkedList, we just nullify the first node. If there are a large no of these linkedlists are created in a language where explicit GCis required(C++), but remain in the thread scope, it can lead to memory leak.
Garbage Collection is the solution to explict memory management.
dangling reference problem is solved because object having some reference is never garbage collected.
memory leaks problem is solved because it automatically frees all memory which is no longer referenced.
allocating memory for objects.
ensuring that any referenced object remains in memory.
recovering memory used by objects that are no longer accessible by any live running threads in the application.
Space is commonly allocated from a large pool of memory called The Heap.
the main problem for a dynamic memory allocation algorithm is to avoid fragmentation while keeping both allocation and deallocation efficient.
in simple words, fragmentation is the space/memory blocks left between the continous memory space which happens because of allocation of memory to objects.
When the memory in the heap is full, and there is no more memory to allocate, then the GC happens.
If the heap size is small, heap fills up quickly, and GC happens frequently(not good), but GC takes less time for completion(good).
If the heap size is large, heap will fill up slowly, and GC will happen infrequently, however it will take long time to complete.
The space left between two memory allocations is called fragmentation on disk.
memory is freed in small chunks, instead of continuous blocks.
so it is possible that there is enough memory to be allocated to a large object, but it is not continous, so the memory cannot be allocated to it.
Compaction is required for removing fragmentation, and freeing up larger continous blocks of memory.
Compaction is part of many GC algorithms.
Design Choices on the type of Garbage Collector.
Serial Vs Parallel GC
In serial, only one thing happens at a time. Even though multiple CPUs are available, only one is used.
In parallel, multiple CPUs are used, and the GC is done quickly, but fragmentation happens.
Concurrent Vs Stop the World GC
In Stop the world GC, the application is paused, and the GC algorithm is simpler and requires less heap size.
When Concurrent GC runs, the application is not paused for most times, but still there are some "stop the world" pauses.
concurrent GC requires higher heap size.
Compacting Vs Non Compacting Vs Copying GC
Compacting GC compacts the space to avoid fragmentation, so that a single pointer can be used to keep track of space for next allocation.
Non Compacting GC does not compact the space, is faster, but it leads to fragmentation.
Copying Collector GC copies the live objects to another area, so that the whole existing area could be freed. There is no fragmentation in it, but it takes a bit more time, and requires extra space.
Real World Applications
An Interactive application, where a user interacts with application a lot(like an application used by bankers for checking the balance) will mostly need lower pause times, so it may want a parallel type GC collector.
A non interactive application will need less overall execution time, so it may use a Stop the world type GC collector.
A real world application will want less pause time, and less GC overhead.
Application on low memory devices need GC types which should have smaller memory footprint, so may be "Stop-the-World" GC is ok for them, because concurrent GCs need more memory.
Throughput is the % of total time not spent in GC.
GC overhead is the % of time spent in GC.
Pause Time is the length of time application is stopped during GC.
Frequency is how often GC happens, relative to application execution.
Footprint is a measure of size, mostly heap size.
Promptness is time between between when the object is freed, and when its memory becomes available to be allocated to another object.
Memory is divided into generations.
There are different pools holding objects of different ages.
Normally there are two kinds of objects in memory: Young Objects and Old Objects.
Generational Collection Algo is based on the following assumptions.
most objects die young.
most(almost all) objects in older generations donot refer to objects in the young generation.
the above allows objects in the young generation to be garbage collected.
Young gen collection happens frequently, and is fast because Young generation area is small and contains lots of objects which are not referenced.
objects which survive few GCs when they are in Young generation are moved to the Old generation.
Old generation is composed of objects which are in memory for larger duration than objects in Young gen, GC happens less frequently in Old Gen, and takes longer to complete.
GC for Young gen happen frequently, so speed is considered important.
GC for Old gen happen less often and should really remove objects because otherwise the heap size will become full, so it should be efficient(and lesser emphasis is on speed).
Young Generation, Old Generation, Permanent Generation(PermGen)
All Objects are initially in Young Gen, objects which survive the Young Gen GC are moved to Old Generation.
PermGen holds objects that the JVM finds convenient to have GC manage, like objects describing classes, methods, and class, methods.
Has 1 Eden and 2 Survivor spaces.
Most objects are initially in Eden.
Survivor holds objects that have survived atleast one GC.
At any time, one survivor holds objects, while the other is empty, till the next collection, when the second one fills up.
Young gen Garbage collection is called minor collection.
Full Garbage Collection
Old gen Garbage collection is called full/major collection, because it involves running first on Young gen, then on Old gen, and then on permgen(with old gen algo) and compacting(if algo wants).
Young Gen GC
Old Gen GC
Fast Allocation and TLABs(Thread-Local allocation buffer)
After compaction, normally memory can be allocated to an object by storing the place where the next memory block is available for allocation.
but there are many threads trying to allocate memory to their objects, and it needs to be done in threadsafe manner.
so each thread is allocated space for it called TLab(ThreadLocal Allocation Buffer), so that there is no locking involved.
both young and old gen collections are done serially(using only one processor, and not concurrently).
young gen collection is done using the usual algo.
old gen collection is done using 'MARK SWEEP COMPACT' algorithm.
Mark phase finds out which objects are reachable from current running threads.
Sweep phase removes the non marked objects.
Compact phase compacts the space, moves the live objects towards the start of the space, and leaves empty space at end.
Parallel Collector/Throughput Collector
A "Stop the world collector", but performs young gen collection in parallel, uses many CPUs, decreases overhead, increases throughput.
Old gen collection uses the same 'Mark Sweep Compact' algo.
Out of Memory Error
Could be because of any of the below:
means object could not be allocated on the heap.
max heap size -Xmx is insufficient for the application, or the application is unintentionally holding references to them.
Java Heap Analysis Tool(JHAT) can be used to see objects and their references.
PermGen is the logical space where information related to metadata is stored.
Metadata includes information about classes, methods and other internal JVM objects, are stored in PermGen
Interned Strings obtained by str.intern() are also stored in Perm Gen. For more info about interned string, click here.//TODO
If we load a large no of classes or strings, we get this error.
defined using MaxPermSize, eg. -XX:MaxPermSize=256M
Requested Array Size Exceeds Limit
if app tries to allocate an array of larger size than the heap size, eg size 512 MB with heap size 256 MB.
Concurrent Mark Sweep Collector(CMS Collector)
Also known as Low Latency Collector.
it is good for applications that require Faster response time and don't worry too much about throughput, because it does everything concurrently without (m)any stop the world pauses.
Young Gen collection is same as Parallel Collector.
Old Gen collection is done concurrently with the application.
'Initial marking phase' identifies the objects directly which are reachable from application.
'Concurrent marking phase' marks all live objects reachable from the above.
'Remarking phase' remarks again all new objects that would have come up in the above process.
At the end of 'remarking phase', all live objects have been marked.
'Concurrent Sweep Phase' removes all garbage.
CMS does not compact, so cannot use pointer technique.
keeps linking together unallocated regions of memory.
Allocations are more expensive because of fragmentation.
Requires more Heap size than the normal collectors because it is more complex and there are no stop the world stops.
During 'Remark' phase, some objects may become garbage, and they will not be reclaimed till next collection and are called'Floating Garbage'.
Fragmentation may occur in Concurrent Mark and Sweep, so it may split or join free blocks to have a larger chunk of memory for allocation.
Concurrent Mark and Sweep happens more frequently and does not wait for the old gen to be full to start old gen collection.
Parallel Compacting Collector
young gen collection is done parallelly so its very fast, but not guaranteed to be very efficient.
old gen is different, first the space is divided into three regions.
then MARK phase happens in parallel.
as the object is identified as live, its info and location is kept.
SUMMARY phase operates on regions, not objects.
the dense regions are not compacted because there will not be much gain by compacting dense regions.
The Strategy should specify the desired behaviour rather than exact heap size values.
We should see whether our application can afford to have a stop the world pause or not, or whether it should always be up and responding.
If parallel or parallel compacting, we should specify a throughput goal.
The heap will change so that the goal can be attained.
If the throughput goal can be met, but there are long pauses, select a maximum pause goal time.
Tools to evaluate
prints memory related stats for running JVM(not in windows)
-heap option : displays information like name of GC, algo-specific details, heap config info, and heap usage summary.
-histo option : displays class wise information of the heap.
-permstat option : displays stats for objects in permanent generation.