memory management: what you need to know when moving to java 8
DESCRIPTION
This presentation will compare and contrast application behavior in Java 7 with Java 8, particularly focusing on memory management and usage. Several code examples are presented to show how to recognize and respond to common pitfalls.TRANSCRIPT
Memory ManagementWhat You Need To Know When Moving to Java 8
Todd Rader, Architect / Sales Engineer
AppDynamics
Market Leadership175% Bookings Growth 2013
1000+Customers
OUR
PLATFORM
Website download
Rapid Time to Value
Low cost of ownership
$Enterprise adoption
Scalable - largest APM deployments
On-Premise, SaaS, Hybrid
No professional Services
84Net Promoter Score
OUR
APPDYNAMICS
Copyright © 2014 AppDynamics. All rights reserved. 2
Copyright © 2014 AppDynamics. All rights reserved. 3
Agenda
• Memory Basics• …with a dive into metaspace
• Fun With Garbage Collectors• GC bake-off
• Summary/Conclusions• Q&A
Copyright © 2014 AppDynamics. All rights reserved. 4
Memory Basics: Types of Memory
STACK• Each thread has its own call stack• Adjust with -Xss• 64-bit JVMs need more stack size (8-byte references)• Default stack size: ????
Java7, jdk1.7.0_51, 64-bit on MacOS 10.9.6• Call depth before StackOverflowError: 10,827 (consistently)
Java8, jdk1.8.0_05, 64-bit on MacOS 10.9.6• Call depth before StackOverflowError: 20,000-ish (huh?)
Copyright © 2014 AppDynamics. All rights reserved. 5
Stack (cont’d)
FUN WITH NUMBERS….• With Java8 default stack size, call depth = 20,000-ish• Using –Xss1024k, same result (SO: default –Xss=1024k)• Using –XX:ThreadStackSize=1024, same result (-
XX:ThreadStackSize is another way of expressing –Xss)
Okay, but…
• -Xss512k result: 9000-ish• Not quite linear!
Need more memory space? Use a smaller –Xss value!• 200 threads * 512kb/thread = 100 MB saved!• What is your true stack size requirement?
Copyright © 2014 AppDynamics. All rights reserved. 6
Memory Basics: Types of Memory (cont’d)
HEAP• Eden/New vs. Survivor vs. Old/Tenured• “Ideal Object Death Rate”
• Eden >> Old >> Survivor
Copyright © 2014 AppDynamics. All rights reserved. 7
Heap (cont’d)
HEAP• What is your object survival demography?
• Caching!• Find out with:
• -XX:+PrintGCDetails• -XX:+PrintTenuringDistribution• -XX:+PrintGCTimestamps
• Adjust with:• -XX:NewRatio=n
– Example: NewRatio=2 (oldGenSize) = 2 * (newGenSize)
• -XX:NewSize=n (minimum)• -XX:MaxNewSize=n• -XX:MinFreeHeapRatio=n• -XX:MaxFreeHeapRatio=n
Copyright © 2014 AppDynamics. All rights reserved. 8
Heap: Java 6 HotSpot
Copyright © 2014 AppDynamics. All rights reserved. 9
Memory Basics: Types of Memory (cont’d)
META• PermGen in Java 6• PermGen (sort of) in Java 7• Metaspace in Java 8
while (true) { int length = rnd.nextInt(100); StringBuilder builder = new StringBuilder(); String chars = "abcdefghijklmnopqrstuvwxyz"; for (int i = 0; i < length; i++) { builder.append(chars.charAt(rnd.nextInt(chars.length()))); } interned.add(builder.toString().intern());}
What happens when this code is run?
Copyright © 2014 AppDynamics. All rights reserved. 10
Running the code…
JAVA 6Exception in thread "main" java.lang.OutOfMemoryError: PermGen space
• …in about 8 seconds!
JAVA 7Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
• …and it takes a long time to happen!
JAVA 8• Similar result as with Java 7
Copyright © 2014 AppDynamics. All rights reserved. 11
What happened???
JAVA 6PermGen contains:• Class meta data• Interned strings
JAVA 7• Interned strings moved to Metaspace
JAVA 8• Class meta data also moved to Metaspace
Copyright © 2014 AppDynamics. All rights reserved. 12
Metaspace
REPLACEMENT FOR PERMGEN• NOT JVM memory – native memory!
• BEA/Oracle JRockit• IBM JVM
SOME NEW STARTUP FLAGS• -XX:MetaSpaceSize=n (initial size)• -XX:MaxMetaSpaceSize=n• -XX:MaxMetaspaceExpansion=n• -XX:MaxMetaspaceFreeRatio=n• No default values for size! Max metaspace size is unlimited :-0
• Say goodbye to PermGen problems……right? Right?
Copyright © 2014 AppDynamics. All rights reserved. 13
More Metaspace
OBSOLETES SOME OLD STARTUP FLAGS• All of the “-XX:*Perm*” flags
NEW MEMORY POOL OBJECTS• No more matching on “Perm” for pool name
Copyright © 2014 AppDynamics. All rights reserved. 14
What does this mean?
NO MORE OOM/PERMGEN• But metaspace errors don’t go away • Monitor metaspace, not PermGen• Use –XX:MaxMetaSpaceSize?
• No you will never run out of metaspace• …but your use of native memory can grow unbounded!
• Yes you merely replace “OutOfMemory: PermGen space” with “OutOfMemory: Metaspace”
MONITOR METASPACE• Apps that leak metadata will still leak metadata• Gobbling up metaspace affects the entire system, not just the JVM
• Remember: native memory!
Copyright © 2014 AppDynamics. All rights reserved. 15
Monitoring Metaspace
COMMERCIAL SOLUTIONS• Expect (demand!) metaspace monitoring support to go along with
Java 8 support
JAVA MANAGEMENT BEANS• Update any querying of MBeans to search for Metaspace memory
pool instead of PermGen pools.
JVISUALVM• Metaspace monitoring supported
• …at least in the jvisualvm that is bundled with Jdk1.8.0_05 on MacOS!
Copyright © 2014 AppDynamics. All rights reserved. 16
Memory Basics: Types of Memory (cont’d)
DIRECT• sun.misc.Unsafe
• Used by the JDK (nio classes, for example)
• Out of the scope of this talk!
Copyright © 2014 AppDynamics. All rights reserved. 17
Let’s talk garbage…
PARALLEL GC• Default on Java 7, Java 8
• ParNewGC is the default on Java 6
• Does parallel compaction in Java 6 and 7• -XX:+UseParallelOldGC option in Java 5
CONCURRENT MARK AND SWEEP GC• NOT compacting!• Can be prone to fragmentation of old gen
• very bad full GCs result
G1GC• Only use after jdk1.7.0_u4!• “Experimental” in previous releases
Copyright © 2014 AppDynamics. All rights reserved. 18
The GC Bake-off
GC KILLER PROGRAM• Allocates lots of java.lang.Objects• Allocates fewer long Strings• Keeps objects around for varying lengths of times• Checks heap memory availability
• When low, thousands of memory references are let go of
• No GC tuning options used• 15-minute runs (killed with Ctrl-C)• Java 7 vs. Java 8
Copyright © 2014 AppDynamics. All rights reserved. 19
Java 7, Parallel GC
Copyright © 2014 AppDynamics. All rights reserved. 20
Java 7, Parallel GC
HIGHLIGHTS• No “-XX” option to enable (default)• Heap usage varied between 1500-2750 MB• Reasonable time spent in GC (1.6 seconds/minute)• No major collections
Copyright © 2014 AppDynamics. All rights reserved. 21
Java 7, ConcMarkSweepGC
Copyright © 2014 AppDynamics. All rights reserved. 22
Java 7, ConcMarkSweepGC
HIGHLIGHTS• Enabled with –XX:+UseConcMarkSweepGC• Heap usage held steady around 2000 MB• Huge amount of time spent in GC (24 seconds/minute!)• No major collections
Copyright © 2014 AppDynamics. All rights reserved. 23
Java 7, G1GC
Copyright © 2014 AppDynamics. All rights reserved. 24
Java 7, G1GC
HIGHLIGHTS• Enabled with –XX:+UseG1GC• Heap usage varied between 750-2800 MB• Very reasonable time spent in GC (0.6 seconds/minute)• No major collections
Copyright © 2014 AppDynamics. All rights reserved. 25
The winner for Java 7
G1!• Less time spent in GC• Heap usage max barely more than max using Parallel
• CMS max heap usage was only 2000• CMS min was also near 2000 (very steady)
• Heap usage min best of all three• No major collections• BUT:
• Remember, no GC tuning parameters were used• DO NOT USE G1GC before jdk1.7.0_04
• “Experimental” in prior releases
Copyright © 2014 AppDynamics. All rights reserved. 26
Java 8, Parallel GC
Copyright © 2014 AppDynamics. All rights reserved. 27
Java 8, Parallel GC
HIGHLIGHTS• Incrementally worse than ParallelGC on Java 7
• Higher max heap (2950 vs. 2750)• Higher min heap (1700MB vs. 1500MB)• Roughly the same GC time (1.6 seconds/minute)
• No major collections
Copyright © 2014 AppDynamics. All rights reserved. 28
Java 8, ConcMarkSweepGC
Copyright © 2014 AppDynamics. All rights reserved. 29
Java 8, ConcMarkSweepGC
HIGHLIGHTS• Just……lousy
• HUGE amount of initial time spent in gc• 55 seconds/minute!
• Heap usage steadily declined• From 3000MB to 2000MB
• With all that time spent, you’d think a major collection would be avoided• You’d be wrong • The only run with a major collection
Copyright © 2014 AppDynamics. All rights reserved. 30
Java 8, G1GC
Copyright © 2014 AppDynamics. All rights reserved. 31
Java 8, G1GC
HIGHLIGHTS• Incrementally worse than G1/Java 7
• Heap usage max 2850MB vs. 2800MB• GC time .8 seconds/minute vs. .6 seconds/minute
• No major collections
Copyright © 2014 AppDynamics. All rights reserved. 32
The winner for Java 8, and overall
G1 AGAIN!• CMS not even close• G1 on Java 7 overall winner• Caveats:
• No GC tuning parameters used• Heap-only: very little metadata memory used• MacOS 10.9.4 (Maverick’s)• 2.8 GHz Intel Core i7 processor• 16 GB 1600 MHz memory• Java 7: jdk 1.7.0_51 for MacOS• Java 8: jdk 1.8.0_05 for MacOS
Copyright © 2014 AppDynamics. All rights reserved. 33
GC Tuning
OUT OF SCOPE • 600+ “-XX:” options
• 83 for CMS in Java 7• 82 for CMS in Java 8
• No love for CMSTriggerPermRatio!
• 24 for G1 in Java 7 and 8• Too many to cover!
Copyright © 2014 AppDynamics. All rights reserved. 34
Summary
• Know your object demography• Monitor your metaspace
• Interned strings• Class metadata
• Research the best GC• Watch out for outdated information
• G1GC tests before jdk1.7.0_04
• Re-think CMS GC?• Un-tuned CMS results far worse
FREE trial available:
www.appdynamics.com
Thank you