Skip to content

Instantly share code, notes, and snippets.

@whostolebenfrog
Created March 6, 2013 13:27
Show Gist options
  • Save whostolebenfrog/5099291 to your computer and use it in GitHub Desktop.
Save whostolebenfrog/5099291 to your computer and use it in GitHub Desktop.
Notes from - Martjin Verburg - Garbage collection, the useful parts
Know more - Gil Tene
GC is about tracking live objects, not dead objects.
Poor GC -> OOM, high pauses, long pause times
Hotspot -> C/C++/Assembly
Heap is broken into several generations pools. [all this is tuneable]
-- Eden
-- Suvivor 0 (smaller)
-- Suvivor 1 (smaller)
-- [virtual]
-- eden, survivor grow into this space (reserved space)
-- Old generation pool (tenured) (much larger than young)
-- PermGen pool
-- away from heap
-- intended to hold objects that last a JVM lifetime
-- reloading and recycling of classes occur here
-- going away in Java8
-- going into the meta space - might be a performance problem
-- spring / hibernate problems
Weak generation hypothesis (or young generational hypothesis)
-- most objects die really young - 80 to 90%
-- live for 4 or 5 collections
-- objects die in the scope of an method or loop etc.
-- long lived objects want to live elsewhere we can check them less often and use a differnt strategy
Copy (or stop and copy, cheney's algorithm)
-- go through, are you alive? are the things you are pointing to alive? If yes copy to a new space and reallocate the old space
Mark and sweep (hotspot uses this)
-- find live (mark)
-- delete dead (sweep)
-- tidy up - optional (compact) think like a defrag
[[ worth learning the theory of this as used in lots of places in hotspot ]]
Java objects
-- OOPs - ordinary object pointers.... or you know.... pointers
-- OOPS point to a header
-- header contains a mark bit, am I alive or dead 1 alive, 0 dead
Step 1 (mark and sweep)
-- mark all as dead
-- mark alive as alive
-- that is something that is either alive in the scope or pointed to from something else that is alive
-- trace though all alive and set those that meet the above to alive
-- some are serial, some split the heap and do parallel
Step 2 (m&s)
-- GC roots are made up of
-- live threads
-- objects for sync
-- class loaders
-- some others
-- special case
-- old gen regs into young gen space
[[ there is a lot of tracing to be done - this can be very expensive ]]
Giving java more memory only makes this worse
Step 3 - sweep
-- mark space that dead objects occupy as deleted
-- compact - always attempted before OOM
Heap of fish demo
Young generation pools
-- eden
-- objects added at end of current block
-- survivor 0 and 1
-- only 1 active at once
-- empty is called target - allow us to use the copy collector
When eden is full (passing a threshold - configurable)
-- GC takes place, young generation
-- anything alive gets copied to target space
-- some live objects get copied to old gen (tenured - set by a tenured threshold, defaults to 4 cyles but if you mess with settings becomes 15 without telling you!)
-- target is now the other space
This is happening multiple times per second
Most GC uses multiple threads (may as well)
PS Scavange / ParNew
-- mark and sweep old gen
-- stop the world collector
Premature promotion occurs
-- high memory pressure
-- eden is too small
-- too big for eden
-- too big to be promoted to survivor space
Old generation collectors
-- parallel
-- mark and sweep
PS Mark sweep
-- ParallelOld
-- chop old into sections for each thread
-- mark and sweep
-- special compact phase takes space at the end
-- low occupancy sections get merged, not a full defrag
CMS (concurrent mark and sweep) Old Gen Collector
-- only runs when tenured is about to get full
-- tunable as to what that means
-- NOT stop the world
-- 6 phases, 2 stop the world (kept to minimum), 4 concurrent
-- initial mark (objects adjacent to roots) - STW
-- concurrent dept first marking - concurrent
-- pre-clean (retrace)
-- remark, rescan
-- sweep (STW?)
Concurrent Mode Failure (CMF)
-- when CMS can't complete in time
-- runs a full stop the world GC on both young and old spaces
-- fixes switch cheese, for a while (defrag)
OOME (out of memory exception)
-- > 98% in GC, just give up!
-- < 2% of heap on a full GC
-- allocate and object larger than the heap
-- sometimes when the JVM can't spawn a new thread, but not sure why
He ended up skipping the second part due to time :-(
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment